
织梦仿站教程:模板标签替换与栏目内容调用详解
把一个静态页面改成织梦(DedeCMS)模板,重点不是把 HTML 里的文字逐个换成标签,而是先判断每块内容的来源:站点配置、当前栏目、当前文档、栏目下的文章,还是固定的页面结构。来源判断正确,标签才容易选对;判断错误,则常见表现是首页正常、栏目页显示错栏目、文章页标题重复,或者后台改了内容而前台没有变化。
本文从仿站时常用的模板拆分方法讲起,逐步说明全局变量、字段标签、栏目导航、文章列表、栏目内容和分页的调用方式,并解释它们的适用范围。织梦存在多个版本和定制分支,模板标签的具体解析行为也可能受版本、模型和二次开发影响。下文采用常见 DedeCMS 模板写法;正式使用前,应在本机版本中做小范围验证。
一、先理解模板、标签和生成结果
织梦模板通常是 HTML 与模板标签混合的文件。标签由织梦模板引擎解析,最终生成浏览器能够读取的 HTML。模板本身一般放在当前站点模板目录中,具体目录由站点模板配置决定;常见目录结构中会看到 templets 目录,但不能假设每个站点都使用同一个模板名称或路径。
制作模板时,可以把页面分成三类内容:
- 固定结构:导航布局、页脚栏目、按钮样式等,直接保留 HTML,必要时抽成公共模板。
- 可配置内容:站点名称、站点地址等,从系统配置读取。
- 业务内容:栏目名称、栏目简介、文章标题、正文等,从当前栏目或文档数据读取。
模板标签并不等于“任意位置都能取任意字段”。有的标签必须在栏目页或文章页的上下文中使用;有的标签负责循环输出多条记录;有的标签只是输出一个字段。先确认页面类型和数据上下文,再选择标签,是减少调试时间的关键。
二、仿站前的准备:先确定页面和数据对应关系
不要一上来就把整套 HTML 塞进模板。建议先列出需要生成的页面类型:通常包括首页、栏目列表页、文章内容页;如果站点有专题、单页或自定义模型,也要单独识别。然后在织梦后台确认栏目结构、栏目内容、文章模型和模板绑定关系。
对照静态页面时,可以先做一张简单的映射表:
- 顶部站名:站点配置中的网站名称。
- 主导航:栏目数据,通常按栏目层级生成。
- 栏目页标题、简介:当前栏目的名称和栏目内容。
- 栏目文章列表:当前栏目下的文档记录。
- 文章页标题、正文:当前文档字段。
- 面包屑:当前栏目层级及文档所在栏目。
如果静态页面中某块内容来自外部接口、手工维护文件或自定义数据库表,不能仅凭外观推断它一定能用标准栏目标签取得。此时需要确认站点的数据结构和已有扩展,必要时由后端代码提供数据。
三、公共模板与全局变量
1. 使用 include 拆分公共区域
页头、页脚、公共导航通常会在多个页面重复出现,可以拆成独立模板,再由各页面引用。常见写法如下:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>{dede:global.cfg_webname/}</title>
</head>
<body>
{dede:include filename="head.htm"/}
<main>
<h1>页面主体</h1>
</main>
{dede:include filename="footer.htm"/}
</body>
</html>
{dede:include filename="head.htm"/} 是常见的模板包含写法。filename 所指文件应能从当前模板环境中找到,实际查找位置与模板目录配置和调用环境有关。仿站时不要把本机绝对路径写进模板;更换模板目录或部署环境后,这类路径容易失效。
如果公共区域还需要根据当前页面显示不同状态,例如给当前栏目导航项增加选中样式,不能只把一段完全静态的导航放进页头。应当让导航本身根据栏目数据生成,或在适合的页面上下文中输出状态。include 只是复用模板片段,不会自动为片段提供所有页面变量,也不负责判断导航状态。
2. 输出站点配置
织梦常见全局变量写法是 {dede:global.变量名/}。例如,站点配置中的网站名称常用 cfg_webname,站点地址常用 cfg_basehost:
<header>
<a href="{dede:global.cfg_basehost/}">
{dede:global.cfg_webname/}
</a>
</header>
全局变量的名称取决于系统配置和版本,不能把示例中的名称当成任意变量都存在。某个变量没有输出时,先查看后台配置或站点实际可用的全局变量,不要立即认定模板语法错误。站点域名发生变化后,也要检查生成页面中的链接是否来自配置值,而不是静态写死的旧域名。
四、字段标签:输出当前页面的数据
字段标签通常用于输出当前页面上下文中的单个值。常见形式包括 {dede:field name='字段名'/},部分场景也会见到简写形式。栏目页和文章页可用字段并不完全相同;字段是否存在,还与内容模型、栏目设置和程序版本有关。
1. 文章页标题与正文
在文章内容模板中,常见标题和正文调用形式如下:
<article>
<h1>{dede:field name='title'/}</h1>
<div class="article-body">
{dede:field name='body'/}
</div>
</article>
这里的 body 指常见文章模型中的正文相关字段。若站点使用自定义模型、字段改名,或者正文经过扩展处理,实际字段可能不同。字段没有输出时,应先核对该页面实际绑定的模型和字段名,再检查模板是否绑定到了正确的文章内容模板。
正文通常包含编辑器生成的 HTML,因此它与纯文本标题的处理方式不同。不要为了“安全”而随意把正文整体转义成纯文本,否则段落、链接和格式会被当作字符显示;也不要因此认为任意用户提交的 HTML 都可以直接输出。正文允许哪些标签、哪些账号有编辑权限,应由后台输入校验、权限控制和内容审核共同决定。
2. 栏目页名称与栏目内容
在栏目列表页中,当前栏目的名称常见调用方式为:
<header class="channel-header">
<h1>{dede:field name='typename'/}</h1>
<div class="channel-description">
{dede:field name='content'/}
</div>
</header>
typename 常用于栏目名称,content 常用于栏目内容。栏目内容是否有值,取决于后台是否填写了相应内容,以及当前页面是否确实处于栏目上下文中。栏目页模板错绑、页面并非当前栏目页面、字段在该版本中名称不同,都可能导致空输出。
栏目内容适合放栏目介绍、说明文字等不需要按文章逐条管理的内容。若内容实际是多篇可独立编辑、发布和归档的文章,应建成文档并通过列表调用;把一长串文章硬塞进栏目内容,后续维护、分页和搜索都会不方便。
五、栏目导航与栏目层级
导航属于栏目数据,但需要根据站点结构选择调用方式。织梦常见栏目标签包括 channel 和 channelartlist,两者用途与输出结构不相同。不要因为标签名称相近,就把它们当成可互换的循环标签。
1. 输出一组栏目链接
channel 常用于输出栏目链接列表,模板内容中可通过栏目字段生成链接和名称。例如:
<nav aria-label="主导航">
<ul>
{dede:channel type='top' row='8'}
<li>
<a href="[field:typelink/]">[field:typename/]</a>
</li>
{/dede:channel}
</ul>
</nav>
这里的 type='top' 常用于顶级栏目,row='8' 表示本次输出条数的设置。若需要当前栏目的子栏目,通常要根据页面上下文和栏目结构调整类型参数;不同版本、不同定制代码对类型参数的支持可能有差异,应在本机验证。不要把 row 当作“栏目总数”,它限制的是当前标签循环输出的数量。
字段占位符与外层标签语法不同:在循环体内常见 [field:typename/]、[field:typelink/] 这样的写法。把它们误写成 {dede:field ...},或把循环体占位符放在循环外,往往不会得到预期结果。
2. 输出栏目及其下级内容结构
当页面要按栏目组织内容,例如“栏目标题下面跟若干文章”,可以考虑 channelartlist。它通常用于栏目列表与文章列表组合的场景,具体可用字段和嵌套方式应以当前版本支持为准。下面展示一种常见结构:
{dede:channelartlist typeid='top'}
<section class="channel-block">
<h2>
<a href="{dede:field name='typeurl'/}">
{dede:field name='typename'/}
</a>
</h2>
<ul>
{dede:arclist row='5'}
<li>
<a href="[field:arcurl/]">[field:title/]</a>
</li>
{/dede:arclist}
</ul>
</section>
{/dede:channelartlist}
这类嵌套的核心是:外层提供栏目上下文,内层查询并输出文章。若外层栏目没有文章、栏目被设置为特定类型,或当前版本对嵌套查询的支持与示例不同,页面输出可能和预期不一致。先用一个栏目和少量数据测试,再扩展到完整首页,定位问题会容易得多。
六、文章列表、链接和分页
1. 用 arclist 输出文章列表
arclist 常用于按条件取得文章并循环输出。下面是一个常见的栏目文章列表示例:
<ul class="article-list">
{dede:arclist typeid='2' row='10'}
<li>
<a href="[field:arcurl/]">[field:title/]</a>
<time>[field:pubdate function='MyDate("Y-m-d",@me)'/]</time>
</li>
{/dede:arclist}
</ul>
typeid 用来限定栏目范围,示例中的数字只是演示值,必须替换成站点真实栏目 ID;row 用来限制返回条数。站点对栏目范围、子栏目和排序方式可能还有其他需求,应查阅当前版本的标签说明或直接检查实际生成结果。不要仅通过标签名称推断它会自动只取当前栏目。
上例的日期字段用到了常见日期格式化写法。格式函数和可用字段受织梦版本及环境影响;如果日期格式化出错,可先改为只输出日期字段,确认数据能正常取到,再逐步恢复格式函数。模板中嵌套引号时也要注意:外层属性使用单引号,函数参数使用双引号,避免引号提前结束。
arclist 适合展示有限条数的内容块,例如首页“最新文章”或栏目侧栏推荐列表。若页面需要标准的栏目分页,通常应使用栏目列表模板中的 list 标签,而不是只增加 arclist 的条数。列表标签常见写法如下:
<ul class="article-list">
{dede:list pagesize='10'}
<li>
<a href="[field:arcurl/]">[field:title/]</a>
</li>
{/dede:list}
</ul>
{dede:pagelist listitem="info,index,end,pre,next,pageno" listsize="5"/}
list 一般用于栏目列表页的主列表区域,与该栏目的分页生成过程配合。它不是放到任意首页区域就能自动形成完整分页。pagesize 是每页显示条数的设置,具体能否按此属性生效,取决于当前版本和页面类型;pagelist 应与相应的分页列表上下文配套使用。页面没有分页时,先确认列表模板绑定正确、栏目确实有足够文章,并且已经按织梦的生成流程更新页面。
2. 链接字段不等于固定 URL
栏目链接和文章链接通常由标签字段提供,例如 [field:typelink/]、[field:arcurl/]。这些字段会按照站点的 URL 规则生成地址。仿站时如果把静态 HTML 里的旧地址照搬进循环模板,栏目迁移、域名变化或生成规则调整后就容易出现失效链接。优先使用系统提供的链接字段;只有明确是固定外部地址时,才直接写固定 URL。
七、将静态 HTML 改造成可维护模板
实操时可以按以下顺序逐步替换,而不是一次性改完整站:
- 先保留页面结构。复制静态页面,整理出页头、导航、主体、侧栏、页脚等区域,暂时不改样式。
- 抽取公共片段。把重复的页头和页脚拆到独立模板,通过 include 引用;确认站点实际模板目录和模板绑定后再生成页面。
- 替换可配置内容。将站名等固定配置替换为全局变量,并检查生成 HTML 中的链接和文字。
- 替换页面上下文。栏目页换成栏目名称、栏目内容;文章页换成文章标题、正文等字段。
- 替换重复数据。把静态导航和文章清单改成栏目或文档循环,确认循环字段的名称及链接正确。
- 最后接入分页与样式状态。分页应与栏目列表流程配套;当前栏目高亮等效果应基于可靠的栏目状态实现,不要靠固定字符串猜测。
每完成一步,就生成一个页面并查看源代码。先检查标签是否被解析、数据是否正确,再检查浏览器显示。浏览器里看起来“空白”的区域,可能是数据确实为空,也可能是模板没有进入对应上下文;查看生成后的 HTML 和模板文件,比反复改 CSS 更能快速定位问题。
八、常见错误与排查方法
错误一:标签原样出现在页面上
如果页面直接显示 {dede:field ...} 或 {dede:arclist ...},通常说明模板没有经过织梦解析,或者文件并不是当前页面实际使用的模板。检查模板绑定、生成入口、文件位置和标签是否拼写完整。静态 HTML 文件直接通过 Web 服务器访问,并不会自动执行织梦模板标签。
错误二:栏目名或栏目内容为空
先确认访问的是栏目页,而不是首页或普通静态页;再确认当前栏目绑定了正确模板、后台字段有内容、字段名称适用于当前版本和模型。模板标签取值依赖页面上下文,不能假设任意页面都有 typename 或 content。
错误三:文章列表重复、栏目范围不对
检查 typeid 是否为目标栏目 ID,查询范围是否包括子栏目,外层循环和内层循环是否都在按预期工作。多个列表块如果使用相同的查询条件,就可能重复显示同一批文章。应分别定义清楚每块内容的来源与筛选范围,而不是只调大 row。
错误四:分页标签没有效果
分页通常依赖栏目列表页面及其列表数据,不是把分页标签放到任何模板中就能生成链接。确认当前模板属于可分页的列表页、列表标签和分页标签处于正确页面上下文,并按站点要求重新生成相关页面。只用 arclist 输出首页文章时,不应期待它自动产生栏目分页。
错误五:链接指向错误或生成后失效
检查模板是否写死旧域名或本地路径,栏目与文章链接是否使用了相应字段,以及站点 URL 配置和生成规则是否一致。若后台内容保存后页面仍旧,确认是否需要重新生成静态页面,并检查访问的 URL 对应的是动态页面还是已有静态文件。
错误六:标签嵌套后输出异常
织梦标签不是通用的 PHP 模板语法,不能随意把一个标签嵌入另一个标签的属性中,也不能假设所有标签都支持任意嵌套。先按最简单结构验证外层,再添加内层;查看当前版本支持的嵌套形式。出错时把复杂标签拆开逐项测试,比一次性复制大型模板更容易找到原因。
九、参数、版本和安全边界
标签参数的含义应以当前织梦版本对应的文档或源码为准。本文中的 row、typeid、pagesize 等仅说明常见用途,不代表它们在所有标签、所有版本中都遵循同一限制或默认值。不要凭空给参数设定最大值、允许值或特殊安全属性;需要确认限制时,应查对应版本实现,并在测试环境验证。
模板标签不是安全过滤器。模板把字段写进 HTML 属性、文本节点或 JavaScript 中时,所需的转义方式并不相同。尤其是标题、栏目名称等可能包含特殊字符的字段,不能假设所有织梦版本和定制环境都会自动按正确上下文转义。对可由普通用户提交的内容,应在后端进行输入校验和权限控制;输出时按具体上下文进行适当编码。不要把未经审核的内容拼进脚本、事件属性或 SQL 语句。
对于文章正文这类允许包含 HTML 的内容,应先明确允许的 HTML 范围,并由可信的编辑流程或可靠的内容净化机制控制,而不是简单地把全部正文当纯文本转义,也不是无条件信任任意输入。模板标签只负责取值和输出,不能代替访问控制、内容审核、SQL 参数化或 Web 安全防护。
织梦属于有多个历史版本和大量定制站点的系统。上线前应确认正在运行的版本、模板标签实现、站点权限和更新状态;不要因为某段标签在别人的站点可用,就推断当前站点也具有相同的字段、参数和安全行为。改动前保留模板备份,并先在测试环境生成页面。
十、一个最小化验证清单
- 首页、栏目页和文章页分别绑定了正确模板。
- include 文件路径在当前模板目录和部署环境中有效。
- 全局变量、栏目字段和文档字段在当前版本中确实存在。
- 导航循环输出的栏目数量、层级和链接符合预期。
- 文章列表的栏目范围、条数、排序和分页经过实际验证。
- 生成后的 HTML 中没有残留未解析标签、错误域名或异常空链接。
- 栏目名、标题、正文等内容按照其输出上下文处理,可信与不可信内容边界清楚。
织梦仿站的核心,是把页面结构与内容数据分开:公共结构用模板复用,站点配置用全局变量,当前页面信息用字段标签,重复栏目和文章用循环标签,栏目列表分页则使用对应的列表模板机制。掌握这些边界后,再逐块替换静态页面,既容易验证,也更方便后续维护。




