Spring Boot系列之Thymeleaf模板布局

Thymeleaf 模板布局主要是为了更好的对前端页面进行划分,主要是通过 Thymeleaf 相关语法来对前端页面布局,主要内容如下:

  1. 引用模板片段
  2. 片段表达式语法
  3. 参数化模板片段
  4. 移除模板片段
  5. 模板布局继承

引用模板片段

使用 th:fragment 可以定义布局片段供其他页面引用,在 foter.html 中定义模板片段如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Footer</title>
</head>
<body>
<!--定义布局片段-->
<div th:fragment="copy">
    &copy; 2020 躬行之
</div>
</body>
</html>

上面定义了一个名为 copy 的片段,可以使用 th:insertth:replaceth:include 来移入模板片段,其中 th:include 在 Thymeleaf 3.0 之后就不再推荐使用,在 home.html 中引入模板片段如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Template Layout.</title>
</head>
<body>
    <!--引入模板片段-->
    <div th:insert="~{footer::copy}"></div>
</body>
</html>

运行项目,查看 http://localhost:8080/home,参考如下:

© 2020 躬行之
© 2020 躬行之

下面来看一下 th:insertth:replaceth:include 三个之间的区别,使用三种方式分别引入名称为 copy 的模板片段如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Template Layout.</title>
</head>
<body>
    <!--th:insert、th:replace、th:include的区别-->
    <p>---th:insert、th:replace、th:include的区别---</p>
    <!--直接插入模板片段-->
    <div id="insert" th:insert="~{footer::copy}">insert</div>
    <!--直接替换当前片段-->
    <div id="replace" th:replace="~{footer::copy}">replace</div>
    <!--直接插入指定片段的内容到当前片段中-->
    <div id="include" th:include="~{footer::copy}">include</div>
</body>
</html>

上述代码中三个 div 分别设置了对应的 idinsertreplaceinclude,运行项目之后在浏览器查看源代码如下:

<!--...-->

<!--th:insert、th:replace、th:include的区别-->
<p>---th:insert、th:replace、th:include的区别---</p>
<div id="insert">
	<div>
		&copy; 2020 躬行之
	</div>
</div>
<div>
	&copy; 2020 躬行之
</div>
<div id="include">
	&copy; 2020 躬行之
</div>
<!--...-->

可知三者区别如下:

  • th:insert:直接插入模板片段;
  • th:replace:直接替换当前片段;
  • th:include:直接插入指定片段的内容到当前片段中。

片段表达式语法

模板主要使用了片段表达式,片段表达式语法如下:

  • 〜{templatename::selector}:引入指定模板指定片段名称的模板片段;
  • 〜{templatename}:引入指定模板的所有片段;
  • 〜{:: selector}:同 〜{this:: selector},引入当前模板指定名称的模板片段。

其中 templatename 表示模板名称,如上文中的 footer,selector 表示片段名称,如上文中的 copy

此外 selector 也可以是 ID 选择器、类选择器以及标签,这样就可以在没有定义 th:fragment 的情况下使用相关模板片段了,如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Footer</title>
</head>
<body>
    <div id="head">
        <p>在没有定义th:fragment的情况下使用片段表达式--id</p>
    </div>
    <div class="head">
        <p>在没有定义th:fragment的情况下使用片段表达式--class</p>
    </div>
    <div >
        <span>在没有定义th:fragment的情况下使用片段表达式--span</span>
    </div>
</body>
</html>

可在另一个模板中使用上述相应的代码片段,如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Template Layout.</title>
</head>
<body>
    <!--在没有定义th:fragment的情况下使用片段表达式-->
    <div th:insert="~{footer::#head}"></div>
    <div th:insert="~{footer::.head}"></div>
    <div th:insert="~{footer::span}"></div>
</body>
</html>

运行项目,结果如下:

在没有定义th:fragment的情况下使用片段表达式--id
在没有定义th:fragment的情况下使用片段表达式--class
在没有定义th:fragment的情况下使用片段表达式--span

参数化模板片段

在使用 th:fragment 定义模板片段的时候可以添加参数,如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Footer</title>
</head>
<body>
    <!--在模板片段中添加参数-->
    <div th:fragment="frag(name)" th:assert="${!#strings.isEmpty(name)}">
        <p th:text="公众号名称+':'+${name}">Default</p>
    </div>
</body>
</html>

然后在对应的页面引用上述片段就可以传递对应参数,如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Template Layout.</title>
</head>
<body>
    <!--参数化模板片段-->
    <div th:insert="~{footer::frag(${gzh})}"></div>
    <!--这种写法如果有多个参数,顺序可以变化-->
    <div th:insert="~{footer::frag(name=${gzh})}"></div>
</body>
</html>

上述代码中参数值 gzh=躬行之,运行项目,结果如下:

公众号名称:躬行之
公众号名称:躬行之

作者:躬行之
原文:微信公众号