Spring Boot系列之Thymeleaf模板布局

PS:原文首发于微信公众号:躬行之(jzman-blog)

前面几篇文章尝试了接口开发、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=躬行之,运行项目,结果如下:

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

其中可以在模板片段中使用 th:assert 属性来进行参数验证,也就是只有 th:assert 里面的表达式的值都为 true 才会继续执行,否则则会抛出异常。

移除模板片段

移除模板片段使用的是 th:remove 属性,该属性可设置的值如下:

  • all: 移除所在标签以及所有的子标签;
  • body: 不移除所在标签,只移除对应的子标签;
  • tag: 只移除所在标签,不删除其子标签;
  • all-but-first: 移除所在标签除第一个之外的所有子标签;
  • none : 无任何移除操作。

具体使用方式参考如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<table>
    <tr>
        <th>NAME</th>
        <th>PRICE</th>
        <th>COMMENT</th>
    </tr>
    <!--移除所在标签以及所有的子标签-->
    <tr th:remove="all">
        <td>A</td>
        <td>1</td>
        <td>AA</td>
    </tr>
    <!--不移除所在标签,只移除对应的子标签-->
    <tr th:remove="body">
        <td>B</td>
        <td>2</td>
        <td>BB</td>
    </tr>
    <!--只移除所在标签,不删除其子标签-->
    <tr th:remove="tag">
        <td>C</td>
        <td>3</td>
        <td>CC</td>
    </tr>
    <!--移除所在标签除第一个之外的所有子标签-->
    <tr th:remove="all-but-first">
        <td>D</td>
        <td>4</td>
        <td>DD</td>
    </tr>
    <!--无任何移除操作-->
    <tr th:remove="none">
        <td>E</td>
        <td>5</td>
        <td>EE</td>
    </tr>
</table>
</body>
</html>

主要关注 th:remove 属性设置不同的值运行后的效果,相当于如下页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<table>
    <tr>
        <th>NAME</th>
        <th>PRICE</th>
        <th>COMMENT</th>
    </tr>
    <!--移除所在标签以及所有的子标签-->
    
    <!--不移除所在标签,只移除对应的子标签-->
    <tr></tr>
    <!--只移除所在标签,不删除其子标签-->
        <td>C</td>
        <td>3</td>
        <td>CC</td>
    <!--移除所在标签除第一个之外的所有子标签-->
    <tr>
        <td>D</td>
    </tr>
    <!--无任何移除操作-->
    <tr>
        <td>E</td>
        <td>5</td>
        <td>EE</td>
    </tr>
</table>
</body>
</html>

模板布局继承

模板布局继承使用的还是 th:fragmentth:replace,下面通过案例演示一下模板布局继承的写法,定义要继承的页面如下:

<!DOCTYPE html>
<html th:fragment="layout (title, content)" xmlns:th="http://www.thymeleaf.org">
<head>
    <title th:replace="${title}">Layout Title</title>
</head>
<body>
<h1>Layout H1</h1>
<div th:replace="${content}">
    <p>Layout content</p>
</div>
<footer>
    Layout footer
</footer>
</body>
</html>

继承上述页面的文件将会替换上述 titlecontent 的值,继承上述页面写法如下:

<!DOCTYPE html>
<html th:replace="~{base :: layout(~{::title}, ~{::section})}" xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Page Title</title>
</head>
<body>
<section>
    <p>Page content</p>
    <div>Included on page</div>
</section>
</body>
</html>

运行后的效果如下:

Layout H1

Page content

Included on page
Layout footer

可关注公众号【躬行之】交流学习,点击查看源码

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/jzman/article/details/110033452