Thymeleaf模板引擎标签的使用规则
一:正文
1. 普通替换
接着我们来了解Thymeleaf如何为普通的标签添加内容,比如我们示例中编写的:
<div th:text="${title}"></div>
我们使用了th:text
来为当前标签指定内部文本,注意任何内容都会变成普通文本,即使传入了一个HTML代码,如果我希望向内部添加一个HTML文本呢?我们可以使用th:utext
属性:
<div th:utext="${title}"></div>
并且,传入的title属性,不仅仅只是一个字符串的值,而是一个字符串的引用,我们可以直接通过此引用调用相关的方法:
<div th:text="${title.toLowerCase()}"></div>
除了替换文本,它还支持替换一个元素的任意属性,我们发现,th:
能够拼接几乎所有的属性,一旦使用th:属性名称
,那么属性的值就可以通过后端提供了,比如我们现在想替换一个图片的链接:
<img width="700" th:src="${url}" th:alt="${alt}">
2. 数值运算
Thymeleaf还可以进行一些算术运算,几乎Java中的运算它都可以支持:
<div th:text="${value % 2}"></div>
同样的,它还支持三元运算:
<div th:text="${value % 2 == 0 ? 'yyds' : 'lbwnb'}"></div>
多个属性也可以通过+进行拼接,就像Java中的字符串拼接一样,这里要注意一下,字符串不能直接写,要添加单引号:
<div th:text="${name}+' 我是文本 '+${value}"></div>
3. 流程控制
除了一些基本的操作,我们还可以使用Thymeleaf来处理流程控制语句,当然,不是直接编写Java代码的形式,而是添加一个属性即可。
首先我们来看if判断语句,如果if条件满足,则此标签留下,若if条件不满足,则此标签自动被移除:
<div th:if="${eval}">我是判断条件标签</div>
th:if
会根据其中传入的值或是条件表达式的结果进行判断,只有满足的情况下,才会显示此标签,具体的判断规则如下:
- 如果值不是空的:
- 如果值是布尔值并且为
true。
- 如果值是一个数字,并且是非零
- 如果值是一个字符,并且是非零
- 如果值是一个字符串,而不是“错误”、“关闭”或“否”
- 如果值不是布尔值、数字、字符或字符串。
- 如果值为空,
th:if
将计算为false
- th:if还有一个相反的属性th:
unless
,效果完全相反,这里就不演示了。
我们接着来看多分支条件判断,我们可以使用th:switch
属性来实现:
<div th:switch="${eval}">
<div th:case="1">我是1</div>
<div th:case="2">我是2</div>
<div th:case="3">我是3</div>
</div>
只不过没有Default
属性,但是我们可以使用th:case="*"
来代替:
<div th:case="*">我是Default</div>
最后我们再来看看,它如何实现遍历,假如我们有一个存放书籍信息的List
需要显示,那么如何快速生成一个列表呢?我们可以使用th:each
来进行遍历操作:
<ul>
<li th:each="title : ${list}" th:text="'《'+${title}+'》'"></li>
</ul>
我们还可以获取当前循环的迭代状态,只需要在最后添加iterStat
即可,从中可以获取很多信息,比如当前的顺序:
<ul>
<li th:each="title, iterStat : ${list}" th:text="${iterStat.index}+'.《'+${title}+'》'"></li>
</ul>
状态变量在th:each
属性中定义,并包含以下数据:
- 当前迭代索引,以0开头。这是
index
属性。 - 当前迭代索引,以1开头。这是
count
属性。 - 迭代变量中的元素总量。这是
size
属性。 - 每个迭代的迭代变量。这是
current
属性。 - 当前迭代是偶数还是奇数。这些是
even/odd
布尔属性。 - 当前迭代是否是第一个迭代。这是
first
布尔属性。 - 当前迭代是否是最后一个迭代。这是
last
布尔属性。
通过了解了流程控制语法,现在我们就可以很轻松地使用Thymeleaf来快速替换页面中的内容了。
4. 模板布局
在某些网页中,我们会发现,整个网站的页面,除了中间部分的内容会随着我们的页面跳转而变化外,有些部分是一直保持一个状态的,比如打开小破站,我们翻动评论或是切换视频分P的时候,变化的仅仅是对应区域的内容,实际上,其他地方的内容会无论内部页面如何跳转,都不会改变。
Thymeleaf就可以轻松实现这样的操作,我们只需要将不会改变的地方设定为模板布局,并在不同的页面中插入这些模板布局,就无需每个页面都去编写同样的内容了。现在我们来创建两个页面:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="head">
<div>
<h1>我是标题内容,每个页面都有</h1>
</div>
<hr>
</div>
<div class="body">
<ul>
<li th:each="title, iterStat : ${list}" th:text="${iterStat.index}+'.《'+${title}+'》'"></li>
</ul>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="head">
<div>
<h1>我是标题内容,每个页面都有</h1>
</div>
<hr>
</div>
<div class="body">
<div>这个页面的样子是这样的</div>
</div>
</body>
</html>
现在就有两个Servlet分别对应两个页面了,但是这两个页面实际上是存在重复内容的,我们要做的就是将这些重复内容提取出来。
我们单独编写一个head.html
来存放重复部分:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<body>
<div class="head" th:fragment="head-title">
<div>
<h1>我是标题内容,每个页面都有</h1>
</div>
<hr>
</div>
</body>
</html>
现在,我们就可以直接将页面中的内容快速替换:
<div th:include="head.html::head-title"></div>
<div class="body">
<ul>
<li th:each="title, iterStat : ${list}" th:text="${iterStat.index}+'.《'+${title}+'》'"></li>
</ul>
</div>
我们可以使用th:insert
和th:replace
和th:include
这三种方法来进行页面内容替换,那么th:insert
和th:replace
(和th:include
,自3.0年以来不推荐)有什么区别?
th:insert
最简单:它只会插入指定的片段作为标签的主体。th:replace
实际上将标签直接替换为指定的片段。th:include
和th:insert
相似,但它没有插入片段,而是只插入此片段的内容。
你以为这样就完了吗?它还支持参数传递,比如我们现在希望插入二级标题,并且由我们的子页面决定:
<div class="head" th:fragment="head-title">
<div>
<h1>我是标题内容,每个页面都有</h1>
<h2>我是二级标题</h2>
</div>
<hr>
</div>
稍加修改,就像JS那样添加一个参数名称:
<div class="head" th:fragment="head-title(sub)">
<div>
<h1>我是标题内容,每个页面都有</h1>
<h2 th:text="${sub}"></h2>
</div>
<hr>
</div>
现在直接在替换位置添加一个参数即可:
<div th:include="head.html::head-title('这个是第1个页面的二级标题')"></div>
<div class="body">
<ul>
<li th:each="title, iterStat : ${list}" th:text="${iterStat.index}+'.《'+${title}+'》'"></li>
</ul>
</div>