上一章节我们初步了解了如何使用模板引擎, 现在我们深入了解模板引擎.
“模板引擎(这里指Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的.”
“模板引擎提供特定的格式与语法, 以此为依据将模板转换为标准HTML文档.”
适合服务端后台开发者.
admin.view
库中的template
方法实则为template
库中的compile
方法的引用, 这个方法返回一个函数, 调用返回的函数将会编译模板.
{{ Lua Expression }}
- Lua Expression是一段lua表达式; 作用为输出表达式的结果, 一些特殊符号将会被转义;
{* Lua Expression *}
- Lua Expression是一段lua表达式; 作用为输出表达式的结果, 不会转义任何符号;
{% Lua code %}
- 执行一段Lua代码, 如: {% for i = x, y do %} ... {% end %}
;
{# comments #}
- comments仅作为注释, 不会包含在输出字符串内. 这段语法的作用类似lua内的--
与--[[]]
;
{( template )}
- 导入其它模板文件, 并且支持传参: {("file.html", { message = "Hello, World" })}
;
{-raw-} ... {-raw-}
- 定义在两端之中的内容将不会做任何处理.
这里列出了可能被转义的字符:
&
将会转义为 &
;
<
将会转义为 <
;
>
将会转义为 >
"
将会转义为 "
'
将会转义为 '
/
将会转义为 /
实战以简单为主. 本章设计到内容主要为深入模板, 代码不会映射到其它章节中.
业务模型: 在页面上列出水果糖的个人信息.
<html>
<head>
<title>{*title*}title>
head>
<body>
<h1 align="center">{*title*}h1>
<p>姓名: {*name*}p>
<p>性别: {*sex*}p>
<p>年龄: {*age*}p>
<p>身高: {*height*}p>
<p>婚姻: {*marriage*}p>
body>
html>
local httpd = require "httpd"
local app = httpd:new("http")
local view = require "admin.view"
app:use("/user", function(content)
return view.template("view/books.html") {
title = "水果糖的个人信息",
name = "水果糖",
sex = "男",
age = 29,
height = "176cm",
marriage = "已婚"
}
end)
app:static("static")
app:listen("", 8080)
app:run()
业务场景: 我们现在有X本书, 这些书需要在页面上展示. 根据实际数量按顺序列出。
<html>
<head>
<title>{*title*}title>
head>
<body>
<h1 align="center">{*title*}h1>
{% for _, book in ipairs(books) do %}
<li align="center">{*book*}li>
{% end %}
body>
html>
-- script/main.lua
local httpd = require "httpd"
local app = httpd:new("http")
local view = require "admin.view"
app:use("/books", function(content)
return view.template("view/books.html") {
title = "编程书籍列表",
books = { "C语言基础教程", "MySQL 从入门到精通", "Lua 编程指南", "Lua Web开发指南", "Lua Admin后台开发指南" }
}
end)
app:static("static")
app:listen("", 8080)
app:run()
业务场景: 我们有一些商品, 我们将不展示某些危险商品.
<html>
<head>
<title>{*tiitle*}title>
head>
<body>
<h1 align="center">{*title*}h1>
{% for index, product in ipairs(products) do %}
{% if product.type == "安全" then %}
<ul>
<li>{*"当前索引: " .. index *}li>
<li>{*product.name*}li>
<li>{*product.price*}li>
<li>{*product.type*}li>
ul>
{% end %}
{% end %}
body>
html>
-- script/main.lua
local httpd = require "httpd"
local app = httpd:new("http")
local view = require "admin.view"
app:use("/products", function(content)
return view.template("view/products.html") {
title = "商品列表",
products = {
{ name = "大白兔奶糖", type = "安全", price = 10},
{ name = "霰弹枪", type = "危险", price = 5700 },
{ name = "TNT", type = "危险", price = 1230000 },
{ name = "三星Note7", type = "危险", price = 1500 },
{ name = "C++从入门到弃坑", type = "安全", price = 50},
}
}
end)
app:static("static")
app:listen("", 8080)
app:run()
业务场景: 由于某个模板代码量太多, 我们现在需要将其拆分为head.html
, body.html
.
<html>
{(view/modular/head.html)}
{(view/modular/body.html)}
html>
<head>
<title>{*title*}title>
head>
<body>
<p align="center">{*body*}p>
body>
-- script/main.lua
local httpd = require "httpd"
local app = httpd:new("http")
local view = require "admin.view"
app:use("/products", function(content)
return view.template("view/modular/base.html") {
title = "title头部",
body = "body内容",
}
end)
app:static("static")
app:listen("", 8080)
app:run()
业务场景: 模板之间的嵌套过于复杂
<html>
<head>
<title>{*title*}title>
head>
<body>
{# 这是一段注释, 不会被显示出来! #}
<h1>{*title*}h1>
{#
多行注释也不会被显示出来
<h1>{*title*}h1>
#}
body>
html>
-- script/main.lua
local httpd = require "httpd"
local app = httpd:new("http")
local view = require "admin.view"
app:use("/ignore", function(content)
return view.template("view/ignore.html") {
title = "title头部",
}
end)
app:static("static")
app:listen("", 8080)
app:run()
业务场景: 一些特殊情况下的语法冲突. 例如: 语言代码语法冲突、模板语法冲突.
<html>
<head>
<title>{*title*}title>
head>
<body>
<div id="view"/>
body>
{-raw-}
<script type="text/javascript" id="tpl_mail">
<a href="mailto:{{d.mail}}">{{ d.mail }}</a>
script>
<script type="text/javascript" id="tpl_phone">
<a href="tel:{{d.phone}}">{{ d.phone }}</a>
script>
{-raw-}
html>
-- script/main.lua
local httpd = require "httpd"
local app = httpd:new("http")
local view = require "admin.view"
app:use("/templates", function(content)
return view.template("view/templates.html") {
title = "title头部",
}
end)
app:static("static")
app:listen("", 8080)
app:run()
当我们使用浏览器访问的时候发现框架抛出一个异常: attempt to index a nil value (global 'd')
.
然后我们在发生冲突块的地方加上了{-raw-} ... {-raw-}
标签, 这是告诉lua模板解析器忽略这一段的解析. 再次访问, 就不会再抛出异常了.
技术发展到现在, 很多模板解析器都已经添加了自定义前缀与闭合的功能. 这样使各个框架独立性更高, 遇到冲突的场景也会大大减少.
[candy@MacBookPro:~/Documents/core_framework] $ tree view
view
├── Modular
│ ├── base.html
│ ├── body.html
│ └── head.html
├── books.html
├── ignore.html
├── products.html
├── templates.html
├── test.html
└── userinfo.html
1 directory, 9 files
[candy@MacBookPro:~/Documents/core_framework] $
我们已经学会了如何使用模板, 下面的章节我们将深入学习admin
库.