如何引入公共的头部、底部或侧边栏模板文件?

在安企CMS构建网站时,我们经常会遇到这样的需求:页面的头部(Header)、底部(Footer)或侧边栏(Sidebar)在多个页面中重复出现。如果每次都复制代码,不仅效率低下,后续维护和更新也会变得异常复杂。幸运的是,安企CMS基于Go语言开发,其模板引擎支持类似Django的语法,提供了非常灵活且强大的方式来引入这些公共模板文件,帮助我们实现内容的高效管理和维护。

核心理念在于代码的重用性和结构化。通过将重复出现的内容模块化,我们可以确保网站风格的一致性,减少冗余代码,并极大简化未来的内容更新工作。安企CMS主要通过两种机制来实现这一目标:include标签和extends标签。

1. 使用 include 标签引入代码片段

include标签是用于将独立的、较小的代码片段嵌入到任何需要它们的地方。你可以把它想象成在某个位置“粘贴”另一段预先写好的代码。这种方式非常适合引入那些在页面结构中相对独立、功能明确的组件,比如网站的侧边栏、通用的广告位、联系信息模块或者简单的头部/底部。

使用场景:

  • 侧边栏(Sidebar): 大多数页面可能共享同一个侧边栏,其中包含导航、热门文章、广告等。
  • 部分头部/底部内容: 例如,版权信息区、友情链接列表。
  • 独立的功能模块: 比如某个页面的留言表单、分享按钮组。

如何操作:

首先,将你的公共代码片段保存为一个独立的 .html 文件。通常,为了更好地组织模板文件,我们会将这些片段放在当前主题模板目录下的 partial/ 文件夹中。例如,你可以在 template/你的主题名/partial/ 目录下创建 sidebar.htmlfooter_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>&copy; {% 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.htmlarchive/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 标签 (进阶用法简述)

除了 includeextends,安企CMS的模板引擎还支持 macro 标签,它类似于编程语言中的函数。