上一章节我们初步了解了如何使用模板引擎, 现在我们深入了解模板引擎.
什么是模板引擎
"模板引擎(这里指Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的."
"模板引擎提供特定的格式与语法, 以此为依据将模板转换为标准HTML文档."
模板引擎的适用场景
适合服务端后台开发者.
Lua 模板引擎
admin.view
库中的template
方法实则为template
库中的compile
方法的引用, 这个方法返回一个函数, 调用返回的函数将会编译模板.
1. 基础语法
-
{{ 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-}
- 定义在两端之中的内容将不会做任何处理.
2. 转义字符
这里列出了可能被转义的字符:
-
&
将会转义为&
; -
<
将会转义为<
; -
>
将会转义为>
-
"
将会转义为"
-
'
将会转义为'
-
/
将会转义为/
实战
实战以简单为主. 本章设计到内容主要为深入模板, 代码不会映射到其它章节中.
1. 字段展示
业务模型: 在页面上列出水果糖的个人信息.
<!-- view/userinfo.html -->
<!DOCTYPE html>
<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()
在这里插入图片描述
2. 循环添加
业务场景: 我们现在有X本书, 这些书需要在页面上展示. 根据实际数量按顺序列出。
<!-- view/books.html -->
<!DOCTYPE html>
<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()
在这里插入图片描述
3. 条件渲染
业务场景: 我们有一些商品, 我们将不展示某些危险商品.
<!-- view/products.html -->
<!DOCTYPE html>
<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()
在这里插入图片描述
4. 模板组合
业务场景: 由于某个模板代码量太多, 我们现在需要将其拆分为head.html
, body.html
.
<!-- view/Modular/base.html -->
<!DOCTYPE html>
<html>
{(view/modular/head.html)}
{(view/modular/body.html)}
</html>
<!-- view/Modular/head.html -->
<head>
<title>{*title*}</title>
</head>
<!-- view/Modular/body.html -->
<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()
5. 模板语法的注释
业务场景: 模板之间的嵌套过于复杂
<!-- view/ignore.html -->
<!DOCTYPE html>
<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()
在这里插入图片描述
6. 前、后端模板语法冲突
业务场景: 一些特殊情况下的语法冲突. 例如: 语言代码语法冲突、模板语法冲突.
<!-- view/templates.html -->
<!DOCTYPE html>
<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
库.
网友评论