頁面佈局就是對前端的頁面進行劃分區域,每個區域有不同的職責,佈局是爲了更好地重複利用前端代碼,避免大量重複性的勞動。在現有的前端系統中,頁面佈局成了前端開發最重要的工作之一,Thymeleaf 在設計之初對頁面佈局就有考慮,通過 Thymeleaf 的相關語法可以很容易地實現對前端頁面佈局。
快速入手
Spring Boot 2.0 將佈局單獨提取了出來,需要單獨引入依賴:thymeleaf-layout-dialect。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
</dependency>
首先定義一個代碼片段 copyright.html,放到 layout 目錄下:
<footer th:fragment="copyright">
© 2018
</footer>
th:fragment 定義一個代碼片段,創建 index.html 在頁面任何地方引入:
<body>
<div th:insert="layout/copyright :: copyright"></div>
<div th:replace="layout/copyright :: copyright"></div>
</body>
th:insert 和 th:replace 區別,insert 只是加載,replace 是替換。
Thymeleaf 3.0 推薦使用 th:insert 替換 2.0 的 th:replace。
layout 是文件夾地址,fileName 是文件名,語法這樣寫 layout/fileName:htmlhead,其中,htmlhead 是指定義的代碼片段,如 th:fragment="htmlhead"。
創建一個 indexController,指向 index.html:
@RequestMapping("/index")
public String index() {
return "index";
}
在瀏覽器中輸入網址,http://localhost:8080/index,可以看到以下信息:
© 2018
© 2018
可以看到兩條版權信息,說明兩種方式都可以引入版權頁面信息,這就是 Thymeleaf 最簡單的頁面佈局了。
Thymeleaf 的這種特性,可以讓我們在開發過程中避免寫很多重複的代碼,如果頁面有共同的頭部、尾部或者其他地方均可採用這種技術。
片段表達式
Thymeleaf 3.0 引入了一種新型的表達式,作爲一般 Thymeleaf 標準的語法表達式之一,它就是:片段表達式。
它使用類似 ~{commons::footer} 的語法,作用在 th:insert 和 th:replace 的內部。使用片段表達式支持引入片段的同時傳參來構造目標頁面,大大提高了代碼複用的靈活度。接下來使用一個案例來介紹片段表達式的使用。
創建一個 base.html 基礎頁面,作爲後續其他頁面引入的模板。
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head th:fragment="common_header(title,links)">
<title th:replace="${title}">comm title</title>
<link rel="stylesheet" type="text/css" media="all" th:href="@{/css/myapp.css}">
<link rel="shortcut icon" th:href="@{/images/favicon.ico}">
<script type="text/javascript" th:src="@{/js/myapp.js}"></script>
<th:block th:replace="${links}" />
</head>
<body>
</body>
</html>
使用 th:fragment 創建了一段代碼片段,命名爲 common_header 並且支持傳入兩個參數 title 和 links,並且指明瞭在頁面中使用的位置:
<title th:replace="${title}">comm title</title>
在此位置插入傳入的 title;<th:block th:replace="${links}" />
在此位置插入傳入的 link,th:block 作爲頁面的自定義使用不會展示到頁面中。
接下來創建一個 fragment.html 頁面,來使用上面創建的 common_header 代碼片段。
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head th:replace="base :: common_header(~{::title},~{::link})">
<title>Fragment - Page</title>
<link rel="stylesheet" th:href="@{/css/bootstrap.min.css}">
<link rel="stylesheet" th:href="@{/cs/fragment.css}">
</head>
<body>
</body>
</html>
在 fragment.html 的頁面中使用 th:replace 引入了 common_header
代碼片段,並且在頁面中添加了 title 和 link 作爲參數傳遞到 common_header
頁面中。
在 IndexController 中添加訪問入口:
@RequestMapping("/fragment")
public String fragment() {
return "fragment";
}
重新啓動項目後,在瀏覽器中輸入網址,http://localhost:8080/fragment,右鍵單擊查看源代碼,可以看到以下信息:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Fragment - Page</title>
<link rel="stylesheet" type="text/css" media="all" href="/css/myapp.css">
<link rel="shortcut icon" href="/images/favicon.ico">
<script type="text/javascript" src="/js/myapp.js"></script>
<link rel="stylesheet" href="/css/bootstrap.min.css"><link rel="stylesheet" href="/cs/fragment.css">
</head>
<body>
</body>
</html>
說明 fragment.html 頁面已經引入了 base.html 頁面中的代碼片段,fragment.html 頁面中傳入的 title 和 link 已經成功地插入到了 base.html 頁面的代碼片段中。
這就是片段表達式最常用的使用方式之一,也是版本 3.0 針對頁面佈局推出的最新語法。因爲這一點,許多佈局(或頁面)技術在 Thymeleaf 3.0 中變得更容易使用。
頁面佈局
按照上面這個思路很容易做頁面佈局,按照常用的框架模式,將頁面分爲頭部、左側菜單欄、尾部和中間的展示區來做個示例:
在 templates/layout 目錄下新建 footer.html、header.html、left.html 頁面,內容如下。
footer.html:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"></meta>
<title>footer</title>
</head>
<body>
<footer th:fragment="footer">
<h1>我是 尾部</h1>
</footer>
</body>
</html>
header.html:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"></meta>
<title>header</title>
</head>
<body>
<header th:fragment="header">
<h1>我是 頭部</h1>
</header>
</body>
</html>
left.html:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"></meta>
<title>left</title>
</head>
<body>
<left th:fragment="left">
<h1>我是 左側</h1>
</left>
</body>
</html>
templates 目錄下新建 layout.html 頁面內容如下:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout">
<head>
<meta charset="UTF-8"></meta>
<title>Layout</title>
</head>
<body>
<div >
<div th:replace="layout/header :: header"></div>
<div th:replace="layout/left :: left"></div>
<div layout:fragment="content" > content</div>
<div th:replace="layout/footer :: footer"></div>
</div>
</body>
</html>
引入佈局的語法命名空間:xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout",使用 th:replace 的語法將網站的頭部、尾部、左側引入到頁面中,同時定義了一個代碼片段 content,可以作爲後期頁面正文的替換內容。
後端添加訪問入口:
@RequestMapping("/layout")
public String layout() {
return "layout";
}
啓動後訪問地址:http://localhost:8080/layout,可以看到頁面展示如下:
我是 頭部
我是 左側
content
我是 尾部
可以看出 layout.html 頁面已經成功地引入了頁面的頭部、尾部、左側。接下來以 layout.html 作爲一個頁面模板,任何頁面想使用此佈局時,只需要替換中間的 content 模塊即可,新建 home.html 來測試:
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout" layout:decorate="layout">
<head>
<meta charset="UTF-8"></meta>
<title>Home</title>
</head>
<body>
<div layout:fragment="content" >
<h2>個性化的內容</h2>
</div>
</body>
</html>
<html>
標籤中添加 layout:decorate="layout" 使用 layout.html 頁面的佈局。<div layout:fragment="content" >
替換 layout.html 頁面中的 content 代碼片段。- layout:decorator 標籤在 3.0 過期,推薦使用新的標籤 layout:decorate 進行頁面佈局。
Controller 添加訪問:
@RequestMapping("/home")
public String home() {
return "home";
}
重啓後,在瀏覽器中輸入網址 http://localhost:8080/home,發現 home.html 頁面已經採用了 layout.html 的頁面佈局,content 部分的內容被替換爲:“個性化的內容”,展示內容如下:
我是 頭部
我是 左側
個性化的內容
我是 尾部
這樣其他頁面如果都是類似的結構都可以採用這樣的方式來使用。
採用頁面模板佈局的時候有兩個關鍵設置:
- 在模板頁面定義需要替換的部分 layout:fragment="content";
- 在需要引入模板的頁面頭部寫 layout:decorate="layout"",再修改 layout:fragment="content" 中的內容。
總結
通過本課的學習發現 Thymeleaf 對代碼片段重複利用、頁面佈局都有很好的支持,Thymeleaf 3.0 引入代碼片段語法更加方便佈局技術的使用。Thymeleaf 3.0 的頁面佈局技術,降低了後端開發人員學習頁面佈局的成本,使用頁面佈局技術後會高效地複用前端頁面,減少了開發量、穩定前端頁面結構。