PS:如果暫時不能讓自己自律起來,那就想讓自己忙起來。
前面幾篇文章嘗試了介面開發、Thymeleaf 模板及其常用語法,閱讀本文之前可以閱讀前面幾篇:
Thymeleaf 模板佈局主要是為了更好的對前端頁面進行劃分,主要是通過 Thymeleaf 相關語法來對前端頁面佈局,主要內容如下:
- 引用模板片段
- 片段表達式語法
- 參數化模板片段
- 移除模板片段
- 模板佈局繼承
引用模板片段#
使用 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">
© 2020 躬行之
</div>
</body>
</html>
上面定義了一個名為 copy 的片段,可以使用 th:insert
、 th:replace
和 th: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:insert
、 th:replace
和 th: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
分別設置了對應的 id
為 insert
、replace
和 include
,運行項目之後在瀏覽器查看源程式碼如下:
<!--...-->
<!--th:insert、th:replace、th:include的區別-->
<p>---th:insert、th:replace、th:include的區別---</p>
<div id="insert">
<div>
© 2020 躬行之
</div>
</div>
<div>
© 2020 躬行之
</div>
<div id="include">
© 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:fragment
和 th: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>
繼承上述頁面的檔案將會替換上述 title
和 content
的值,繼承上述頁面的寫法如下:
<!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