模板和渲染
【E2EE文档】

模板和渲染

E2EE默认模板引擎使用简单高效,支持循环、条件判断和异常提示。

模板位置以当前网站的“模板”目录做为根目录。

指定模板目录和模板相关的设置请参考之前的《创建网站和配置》章节。

本章节索引:

  1. 渲染
  2. 模板
  3. 转义符
  4. 模板过滤器

1. 渲染

渲染是将数据,通过模板定义的数据展现方式,动态生成需要的文本内容。

E2EE中的模板渲染主要分三部:

  • 注册视图函数时指定模板位置
  • 在视图函数中生成模板需要的数据
  • 执行渲染输出网页

1.1 注册视图函数时指定模板位置

假如您的网站目录结构是这样的:

  [网站]
    │ 配置.conf
    ├─临时
    ├─日志
    ├─模块
    ├─模板
    │      login.esp
    ├─网页
    │      404.html
    └─配置

注册视图函数时,第三个参数为模板文件路径,路径是以“模板”目录为根目录的相对路径。

留言本服务器.订阅视图函数 (&留言本_登录页, “/login”, “/login.esp”, )

此时模板就已经成功定位到了 [网站]/模板/login.esp 下了。

模板路径建议以“/”开始,这样更便于阅读。允许不带开头的“/”,当使用“./”、“/” 和 不带“/”的 效果是一样的。

模板路径允许使用相对目录符号来重新定向到其它位置,例如:../网页/login.esp 。这时模板就被定位到了 [网站]/网页/login.esp 。一般不建议把模板放在“模板”目录外。

1.2 在视图函数中生成模板需要的数据

渲染时需要提供一个“存取键值表”类型的变量做为模板渲染数据。

模板引擎是根据主键的名称来获取内容并生成数据的。下面是一个典型的模板数据(存取键值表)文本展开形式,其中用户列表为“存取列表”类型的数据:

{
    当前分页:   1
    总分页数:   5
    用户列表:   [
                    {
                        名称: "JimStone"
                        性别: "男"
                        身高: 172
                    }
                    {
                        名称: "帝霸禁烟"
                        性别: "男"
                        身高: 110
                    }
                    {
                        名称: "阿彬"
                        性别: "女"
                        身高: 160
                    }
                    {
                        名称: "心宇"
                        性别: "男"
                        身高: 178
                    }
                ]
}

您在处理完业务逻辑后,组装类似上面结构的数据提交给模板引擎就行了。

当模板引擎渲染时,能够根据名称取到所有需要的数据。譬如模板中写入了“第{{当前分页}}页”这样的内容,则渲染时会自动将文本替换为“第1页”。同样的道理,用户列表中的每一项也都能够输出为您需要的格式。

感觉这种格式非常复杂?

这都不是问题,E2EE提供了非常简单快速构建 键值表 和 列表 的函数(请查看《通用存取对象》章节),同时您的 自定义数据类型 也能通过 ORM 系统在键值表和存取列表之间自由的转换(这部分请查看后边的章节)。

下面是一段组装数据的例子:

1.3 执行渲染输出网页

模板渲染只需要执行 响应.渲染。

返回 (响应.渲染 (模板数据, , ))

其中的模板数据就是之前您组装的数据。

响应的渲染方法,除了对定义好的模板文件进行渲染,还能够选择不同的模板文件。以下是响应渲染方法的原型:

渲染() : 逻辑型

渲染内容并输出到页面。

  • 模板数据:“存取键值表”,可以被省略。需要生成模板的来源数据。如果模板数据为空,则默认传递 请求.属性表() 用于模板渲染。

  • 模板路径:“文本型”,可以被省略。重新指定模板文件的相对路径。如果为空则使用当前请求相对路径对应的模板。

  • 渲染文档类型:“文本型”,可以被省略。返回给浏览器的HTTP头部Content-Type内容。如果为空则使用服务器配置()。具体格式请查看《创建网站和配置》章节中的MIMEMAP说明。

2. 模板

默认模板引擎支持以下几种类型的内容输出:

  • 输出变量
  • 列表循环
  • 条件判断
  • 包含文件

所有形式的渲染都是以两个起始大括号“{{”开始和两个结束大括号“}}”结束的标签的形式。例如:

{{用户名}}

列表循环 和 条件判断 都必须定义收尾标签,和 起始标签遥相呼应,一一对应。收尾标签的形式为:

{{#列表数据}}
{{/列表数据}}

其中的 {{/列表数据}}就为收尾标签。

2.1 输出变量

[格式] {{变量名}}

以下是一个标准的变量输出定义:

{{用户名}}

变量名不能以这些字符开头:> # ? !

变量名称建议使用标准英文或者中文,这样也便于阅读,允许使用下划线和中划线。

[示例]

模板数据:

{
    页面名称:   "首页"
}

模板文件:

<meta charset="UTF-8">
<title>留言本 - {{页面名称}}</title>

最终输出:

<meta charset="UTF-8">
<title>留言本 - 首页</title>

系统隐藏变量


在渲染模板之前,模板引擎会自动注入以下变量以便使用更加方便:

  • {{_服务器名称}}:服务器的名称
  • {{_模块路径}}:当前容器模块的相对路径。
{{_模块路径}} 的作用

用于服务器的容器模块化功能时调用。

在做容器模块功能时,请务必保证动态页面生成的链接带此变量。作为模块化服务器时静态资源路径访问请使用相对路径。

做为主服务器也能够使用此变量,主服务器时此变量值为空。

典型场景如下:
    ...
    <link type="text/css" rel="stylesheet" href="{{_模块路径}}/stylesheets/footer.css">
    <script type="text/javascript" src="{{_模块路径}}/dist/vue.js"></script>
    ...
    <a href="{{_模块路径}}/index.html">首页</a>
    ...

2.2 列表循环

列表循环能够循环一个列表数据,枚举其中的每一项并做输出。

[格式] {{#列表变量}} 每项下级内容 {{/列表变量}}

使用列表循环的格式和使用步骤:

  • 列表枚举起始:{{#列表变量}}
  • 渲染列表数据:输出每一项的下级内容
  • 列表枚举结束:{{/列表变量}}

列表循环的起始格式以“{{#”开头,“}}”结束,中间是变量的名称。

列表循环必须包含收尾标签。收尾标签以“{{/”开头,“}}”结束,中间是和起始格式一样的变量的名称。

起始和结束标签务必配对。

列表循环会从列表第一行一直读取到最后一行,没读一行就会取出当前行的数据并且进行渲染。当列表数据为空时,列表标签内的内容将不会进行输出。

以下是一个标准的列表循环定义:

{{#列表数据}}
...
{{/列表数据}}

[示例]

模板数据:

{
    用户列表:   [
                    {
                        名称: "JimStone"
                        性别: "男"
                        身高: 172
                    }
                    {
                        名称: "帝霸禁烟"
                        性别: "男"
                        身高: 110
                    }
                    {
                        名称: "阿彬"
                        性别: "女"
                        身高: 160
                    }
                    {
                        名称: "心宇"
                        性别: "男"
                        身高: 178
                    }
                ]
}

模板文件:

<ul>
{{#用户列表}}
    <li> {{名称}} - {{性别}} - {{身高}} </li>
{{/用户列表}}
</ul>

最终输出:

<ul>
    <li> JimStone - 男 - 172 </li>
    <li> 帝霸禁烟 - 男 - 110 </li>
    <li> 阿彬 - 女 - 160 </li>
    <li> 心宇 - 男 - 178 </li>
</ul>

列表循环中的隐藏变量


在列表循环过程中,为了使用方便,模板引擎会自动为列表每一项创建一些隐藏变量:

  • {{_下标}}:当前枚举行的行号。从1开始,每次加1。
  • {{_奇偶行}}:当前条目在列表中的位置为奇数行还是偶数行。第一条为奇数,第二条为偶数,第三条为奇数以此类推。 如果为奇数行则对应的值为“1”,偶数行对应的值为“2”。

2.3 条件判断

条件判断的使用方式和 列表循环 差不多。

使用条件判断的格式和使用步骤:

  • 条件判断起始:{{?要判断变量}}
  • 符合条件则渲染标签范围内的数据
  • 条件判断结束:{{/要判断变量}}

条件判断的起始格式以“{{?”开头,“}}”结束,中间是变量的名称或者判断的条件。

条件判断必须包含收尾标签。收尾标签以“{{/”开头,“}}”结束,中间是和起始格式一样的变量的名称。无论起始标签中是否存在条件文本,收尾标签内都只能为变量名称。

起始和结束标签务必配对。

以下是一个标准的条件判断定义:

{{?名称}}
    我叫 {{名称}},我是{{性别}}人
{{/名称}}

为了方便说明各种条件处理情况,我们先定义模板数据:

[条件判断模板数据]

{
    页面名称1:  "首页"
    页面名称2:  ""
    用户列表1:  [
                    {
                        名称: "JimStone"
                        性别: "男"
                        身高: 172
                    }
                ]
    用户列表2:  []

    当前分页:   5
    当前分页文本: "5"
}

以下条件判断格式所有的 [格式] 为 条件结果。即:条件成立 则为 真。为真时则输出内容。

以下条件判断格式所有的 [相反格式] 为 条件结果取反。即:条件成立 则为 假

2.3.1 判断是否不为空

[格式] {{?变量}} 输出内容 {{/变量}}

  • 变量为文本时:文本内容长度大于0时则条件成立(为 真)
  • 变量为列表时:列表行数大于0则条件成立
  • 变量为其它类型的:只要存在条件就成立

[相反格式] {{?!变量}} 输出内容 {{/变量}}

[示例1]

模板文件:

{{?页面名称1}} {{页面名称1}} {{/页面名称1}}

最终输出:

首页

[示例2]

模板文件:

{{?!页面名称2}} {{页面名称1}} {{/页面名称2}}

最终输出:

首页

[示例3]

模板文件:

{{?页面名称1}} 1 {{/页面名称1}}
{{?页面名称2}} 2 {{/页面名称2}}
{{?用户列表1}} 3 {{/用户列表1}}
{{?用户列表2}} 4 {{/用户列表2}}
{{?当前分页}} 5 {{/当前分页}}

最终输出:

1
-
3
-
5

2.3.2 判断是否等于指定文本

[格式] {{?变量="文本内容"}} 输出内容 {{/变量}}

  • 只有变量的文本和对应文本完全一样时条件才成立
  • 值类型为 列表 和 键值表 时此处的条件永远不成立
  • 值类型为文本外的类型时:只有内容跟 键值表.取文本() 完全一致时条件才成立

[相反格式1] {{?变量!="文本内容"}} 输出内容 {{/变量}}

[相反格式2] {{?!变量="文本内容"}} 输出内容 {{/变量}}

[示例]

模板文件:

{{?页面名称1="首页"}} 1 {{/页面名称1}}
{{?页面名称2="首页"}} 2 {{/页面名称2}}
{{?用户列表2=""}} 3 {{/用户列表2}}
{{?当前分页="5"}} 4 {{/当前分页}}
{{?当前分页="5.0"}} 5 {{/当前分页}}

最终输出:

1
-
-
4
-

2.3.3 判断是否等于指定数值

[格式] {{?变量=数值}} 输出内容 {{/变量}}

  • 只有变量转换为数值后能和对应的数值相等时条件才成立
  • 值类型为 列表 和 键值表 时此处的条件永远不成立
  • 文本型和其它类型的数据:只要数值跟 键值表.取文本()转换为数值后一致时条件就成立

[相反格式1] {{?变量!=数值}} 输出内容 {{/变量}}

[相反格式2] {{?!变量=数值}} 输出内容 {{/变量}}

[示例]

模板文件:

{{?页面名称2=5}} 1 {{/页面名称2}}
{{?用户列表2=0}} 2 {{/用户列表2}}
{{?当前分页=5}} 3 {{/当前分页}}
{{?当前分页文本=5}} 4 {{/当前分页}}

最终输出:

-
-
3
4

2.3.4 判断是否等于指定变量

[格式] {{?变量1=变量2}} 输出内容 {{/变量1}}

  • 判断结果依赖于变量转换为文本后的内容是否一致。

[相反格式1] {{?变量1!=变量2}} 输出内容 {{/变量1}}

[相反格式2] {{?!变量1=变量2}} 输出内容 {{/变量1}}

[示例]

模板文件:

{{?页面名称2=5}} 1 {{/页面名称2}}
{{?用户列表2=0}} 2 {{/用户列表2}}
{{?当前分页=5}} 3 {{/当前分页}}
{{?当前分页文本=5}} 4 {{/当前分页}}

最终输出:

-
-
3
4

2.3.5 多条件判断

或 ||

判断 [表达式1成立] 或 [表达式2成立]。

{{?表达式1 || 表达式2}} 输出内容 {{/表达式1变量}}

且 &&

判断 [表达式1成立] 且 [表达式2成立]。

{{?表达式1 && 表达式2}} 输出内容 {{/表达式1变量}}

[示例]

模板文件:

{{?当前分页==3 || 当前分页==5}} 3 {{/当前分页}}
{{?当前分页==3 && 当前分页==5}} 3 {{/当前分页}}

最终输出:

3
-

2.4 包含文件

在当前模板中引入其它模板文件。

[格式] {{> 模板文件路径 }}

[示例]

假设当前模板目录为:c:/网站/模板/

当前模板文件路径为:c:/网站/模板/用户/index.esp

页头文件:[网站]/模板/header.esp

<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8">
  <title>留言本</title>
</head>
<body>

页脚文件:[网站]/模板/footer.esp

<body>
</html>

模板文件:[网站]/模板/用户/index.esp

{{> /header.esp }}
  <div class="am-g">
    <a href="#">添加</a>
    <a href="#">删除</a>
  </div>
{{> /footer.esp }}

最终输出:

<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8">
  <title>留言本</title>
</head>
<body>
  <div class="am-g">
    <a href="#">添加</a>
    <a href="#">删除</a>
  </div>
<body>
</html>

2.5 添加注释

在模板中添加注释信息。注释将不会被输出到最终的页面中。

[格式]

{{! 注释内容 }}

当然,也可以让注释更漂亮一些:

{{!-- 漂亮的注释内容 --}}

包含文件路径寻址方式


包含文件的路径支持三种类型的路径:

  • 相对路径(从当前渲染的模板所在目录寻址):
    • header.esp => c:/网站/模板/用户/header.esp
    • ../header.esp => c:/网站/模板/header.esp
  • 以“模板”目录为根的相对路径(以/开头,从“模板”目录寻址):
    • /header.esp => c:/网站/模板/header.esp
    • /用户/header.esp => c:/网站/模板/用户/header.esp
  • 绝对路径(磁盘绝对路径):!!!不建议使用
    • c:/网站/header.esp => c:/网站/header.esp

3. 转义符

如果您想在模板文件中使用“{{”和“}}”这种格式的符号,而不是让模板引擎去渲染,请使用“{\{”和“}\}”来转义。

4. 模板过滤器

4.1 使用方法

在普通输出标签变量名称后加入"|" + 过滤函数。

例如:

  • 输出标签:

    {{金额}}
    
  • 加入过滤器:

    {{金额 | 小数格式化(2)}}
    

4.2 过滤器函数手册

  • 赋值([值内容])

    【不输出内容】 给变量赋值为指定内容。

    [值内容] 值内容为文本型。需要通过引号“"”指定内容。

    {{标题 | 赋值("E2EE首页")}}

  • 增减([数量])

    【不输出内容】 增减对应的数值变量。如果变量内容不为数值或数值文本,则变量内容自动变为0。

    [数量] 要增减的值。

    {{数量 | 增减(2)}}

    200 => 202
    
  • 连接文本(要连接的参数,...)

    【不输出内容】 连接文本变量等并且将连接文本内容赋值给当前变量。(更新于1.6.11)

    [要连接的参数] 要连接的文本、变量或数值等,允许多参数。

    例如: 变量 [标题] 鲁智深 [副标题] 拳打镇关西

    {{标题 | 连接文本("标题:", 标题, " - ", 副标题)}}

    [标题] => “标题:鲁智深 - 拳打镇关西” 
    
  • 小数格式化([小数数量])

    保留小数后的指定位数的数据。如果变量内容不为数值或数值文本,则变量内容自动变为0。

    [小数数量] 指定小数后显示位数的数量

    {{金额 | 小数格式化(2)}}

    200 => 200.00
    300.235 => 300.23
    
  • 货币格式化([货币前缀])

    将数值按照货币格式进行格式化。每千分位以逗号分隔,小数保留两位。例如:3,000,000.00。如果变量内容不为数值或数值文本,则变量内容自动变为0。

    [货币前缀] 货币格式的前缀文本。本参数允许为空。

    {{金额 | 货币格式化()}}

    3000000 => 3,000,000.00
    

    {{金额 | 货币格式化("¥")}}

    3000000 => ¥3,000,000.00
    
  • 时间格式化([格式化文本])

    输出时间格式的文本为指定格式化文本,格式参考 创建文本从时间 的格式。

    [格式化文本] 时间格式文本。需要通过引号“"”指定格式内容。

    {{标题 | 时间格式化("%Y-%m-%d %H:%M")}}
    
  • HTML关键字编码()

    将内容中的HTML关键字进行编码。相关关键字主要包含 <、>、'、" 等。

    {{标题 | HTML关键字编码()}}

    我们<strong>家</strong>的"孩子" => 我们&lt;strong&gt;家&lt;/strong&gt;的&quot;孩子&quot;
    
  • HTML关键字解码()

    将内容中的HTML关键字进行解码。相关关键字主要包含 <、>、'、" 等。

    {{标题 | HTML关键字解码()}}

    我们&lt;strong&gt;家&lt;/strong&gt;的&quot;孩子&quot; => 我们<strong>家</strong>的"孩子"
    

4.3 测试模板

  • 数据

    {
        小数:     "10000000000001.3010000002"
        小数位数:   "6"
        时间:     "2017-04-13 20:12:10"
        时间格式:   "%m-%d %H:%M"
        货币:     "3000000"
    }
    
  • 模板

    小数:{{ 小数 | 小数格式化(小数位数) }}
    时间:{{ 时间 | 时间格式化(时间格式) }}
    货币:{{ 货币 | 货币格式化() }}
    赋值:{{ 页数 | 赋值("5") }}[{{ 页数 }}]
    增减:{{ 页数 | 增减(-3) }}[{{ 页数 }}]
    
  • 生成

    小数:10000000000001.301000
    时间:04-13 20:12
    货币:¥3,000,000.00
    赋值:[5]
    增减:[2]