banner
jzman

jzman

Coding、思考、自觉。
github

Spring Boot系列之Thymeleaf模板佈局

PS:如果暫時不能讓自己自律起來,那就想讓自己忙起來。

前面幾篇文章嘗試了介面開發、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
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。