在安企CMS构建网站时,我们经常会遇到这样的需求:页面的头部(Header)、底部(Footer)或侧边栏(Sidebar)在多个页面中重复出现。如果每次都复制代码,不仅效率低下,后续维护和更新也会变得异常复杂。幸运的是,安企CMS基于Go语言开发,其模板引擎支持类似Django的语法,提供了非常灵活且强大的方式来引入这些公共模板文件,帮助我们实现内容的高效管理和维护。
核心理念在于代码的重用性和结构化。通过将重复出现的内容模块化,我们可以确保网站风格的一致性,减少冗余代码,并极大简化未来的内容更新工作。安企CMS主要通过两种机制来实现这一目标:include标签和extends标签。
1. 使用 include 标签引入代码片段
include标签是用于将独立的、较小的代码片段嵌入到任何需要它们的地方。你可以把它想象成在某个位置“粘贴”另一段预先写好的代码。这种方式非常适合引入那些在页面结构中相对独立、功能明确的组件,比如网站的侧边栏、通用的广告位、联系信息模块或者简单的头部/底部。
使用场景:
- 侧边栏(Sidebar): 大多数页面可能共享同一个侧边栏,其中包含导航、热门文章、广告等。
- 部分头部/底部内容: 例如,版权信息区、友情链接列表。
- 独立的功能模块: 比如某个页面的留言表单、分享按钮组。
如何操作:
首先,将你的公共代码片段保存为一个独立的 .html 文件。通常,为了更好地组织模板文件,我们会将这些片段放在当前主题模板目录下的 partial/ 文件夹中。例如,你可以在 template/你的主题名/partial/ 目录下创建 sidebar.html 或 footer_links.html。
假设我们创建了一个 partial/sidebar.html 文件,内容如下:
<aside class="sidebar">
<h3>最新文章</h3>
<ul>
{% archiveList archives with type="list" limit="5" %}
{% for item in archives %}
<li><a href="{{item.Link}}">{{item.Title}}</a></li>
{% endfor %}
{% endarchiveList %}
</ul>
<h3>联系我们</h3>
<p>电话:{% contact with name="Cellphone" %}</p>
<p>邮箱:{% contact with name="Email" %}</p>
</aside>
然后在你需要显示这个侧边栏的页面模板中,使用 {% include %} 标签来引入它:
<!-- index.html 或 detail.html 等页面中 -->
<div class="main-content">
<!-- 页面主体内容 -->
</div>
<div class="right-sidebar">
{% include "partial/sidebar.html" %}
</div>
更灵活的用法:
- 可选引入: 如果某个片段可能存在也可能不存在,可以使用
if_exists避免报错:{% include "partial/ad_banner.html" if_exists %} - 传递数据: 你甚至可以给
include的模板传递特定的变量,让它显示不同的内容:
在{% include "partial/hero_section.html" with title="欢迎访问安企CMS" subtitle="高效易用的内容管理系统" %}hero_section.html中就可以使用{{ title }}和{{ subtitle }}了。
2. 使用 extends 标签构建页面骨架
extends标签用于定义一个通用的页面骨架或布局,子页面可以继承这个骨架,并只修改其中特定的内容块。这就像建筑蓝图一样,你定义了房子的基本结构(墙壁、屋顶),然后在每个房间(子页面)里可以自由地装修(填充内容)。这种方式非常适合管理网站的整体布局,包括全局的头部、底部以及主要的区域划分。
使用场景:
- 网站的整体布局: 定义一个包含
<head>区域、主导航、主内容区、底部版权信息等在内的base.html。 - 不同类型的页面布局: 例如,文章详情页和产品列表页可能共享大部分布局,但主内容区域的结构会有所不同。
如何操作:
首先,创建一个基础布局文件,通常命名为 base.html,并放置在你的主题模板根目录下。在这个 base.html 中,使用 {% block 块名称 %}{% endblock %} 来定义可被子模板覆盖的内容区域。
一个 base.html 的例子可能长这样:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{% block title %}{% tdk with name="Title" siteName=true %}{% endblock %}</title>
<meta name="keywords" content="{% tdk with name="Keywords" %}">
<meta name="description" content="{% tdk with name="Description" %}">
<link rel="stylesheet" href="{% system with name="TemplateUrl" %}/css/main.css">
{% block head_extra %}{% endblock %} {# 留给子模板添加额外CSS/JS #}
</head>
<body>
<header class="header">
<a href="{% system with name="BaseUrl" %}"><img src="{% system with name="SiteLogo" %}" alt="{% system with name="SiteName" %}"></a>
<nav class="main-nav">
{% navList navs %}
<ul>
{% for item in navs %}
<li><a href="{{ item.Link }}">{{item.Title}}</a></li>
{% endfor %}
</ul>
{% endnavList %}
</nav>
</header>
<main class="container">
<div class="content-wrapper">
{% block content %}{% endblock %} {# 这是主内容区域,子模板会在这里填充 #}
</div>
{% include "partial/sidebar.html" %} {# 这里可以再次使用include引入侧边栏 #}
</main>
<footer class="footer">
<p>© {% now "2006" %} {% system with name="SiteName" %}. All rights reserved.</p>
<p>{% system with name="SiteCopyright" %}</p>
{% block footer_extra %}{% endblock %} {# 留给子模板添加额外JS #}
</footer>
</body>
</html>
然后,在你的具体页面(如 index.html 或 archive/detail.html)中,通过 {% extends %} 标签继承 base.html,并使用 {% block %} 标签来覆盖或填充对应的区域:
{% extends 'base.html' %} {# 声明继承自base.html,这必须是模板文件的第一行 #}
{% block title %}首页 - {% tdk with name="SiteName" %}{% endblock %} {# 覆盖title块 #}
{% block head_extra %}
<link rel="stylesheet" href="{% system with name="TemplateUrl" %}/css/index.css">
{% endblock %}
{% block content %} {# 填充主内容区域 #}
<section class="hero-section">
<h1>欢迎来到我们的网站!</h1>
<p>探索我们的最新内容。</p>
</section>
<!-- 其他首页特有的内容 -->
{% endblock %}
{% block footer_extra %}
<script src="{% system with name="TemplateUrl" %}/js/index_analytics.js"></script>
{% endblock %}
这样,index.html 就自动拥有了 base.html 中定义的头部、导航和底部,而你只需要关注其特有的内容部分。
include vs. extends:何时选择?
简单来说:
extends用于定义页面的整体 布局结构。如果你需要一个包含头部、主内容区和底部等大块区域的通用页面模板,并且大多数页面都遵循这个结构,那么extends是首选。它管理的是页面的“骨架”。include用于引入页面内的 独立组件 或 代码片段。当你在一个已经建立好骨架的页面中,需要某个小块内容(比如侧边栏、广告、用户评论区)在多个地方重复出现时,使用include会更高效。它管理的是页面上的“家具”或“装饰”。
一个页面通常会先 extends 一个基础布局,然后在被 extends 进来的基础布局中,或者在子模板内部的 block 区域中,再使用 include 引入更小的公共组件。
macro 标签 (进阶用法简述)
除了 include 和 extends,安企CMS的模板引擎还支持 macro 标签,它类似于编程语言中的函数。