如何在 Thymeleaf 中插入文字而不移除 HTML 結構
1. 概述
在使用 Thymeleaf 模板引擎時,渲染動態內容很容易無意中破壞 HTML 結構。這種情況通常發生在基於屬性的表達式替換元素內容時,導致輸出不完整。
在本教程中,我們將探討開發者在 Thymeleaf 中渲染動態文字時常犯的錯誤。此外,我們還將探索兩種有效方法來保留預期的 HTML 結構:使用文字內聯和在子元素中渲染動態內容,並可選地使用th:remove=”tag”來優化標記。
2. 項目設定
首先,讓我們透過在pom.xml中新增spring-boot-starter-web相依性來啟動一個 Spring Boot 專案:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>4.0.2</version>
</dependency>
此依賴項可讓我們編寫具有嵌入式 Web 伺服器的 Spring Web 應用程式。
另外,讓我們把spring-boot-starter-thymeleaf依賴項加入pom.xml中:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>4.0.2</version>
</dependency>
spring-boot-starter-thymeleaf依賴項允許我們使用 Thymeleaf 模板引擎。
最後,我們建立一個控制器類,用於處理對首頁的請求,並將標題和副標題暴露給視圖:
@Controller
public class HomeController {
@GetMapping("/home-page")
public String homePage(Model model) {
String title = "Introduction to Java";
String subtitle = "[Java powers over 1 billion devices]";
model.addAttribute("title", title);
model.addAttribute("subtitle", subtitle);
return "structures/home";
}
}
在上面的程式碼中,我們定義了一個對應到/home-page端點的控制器方法。當發出 GET 請求時,該方法會傳回首頁視圖,並將title和subtitle值作為模型屬性公開。然後,可以在 Thymeleaf 模板中存取這些屬性以進行渲染。
3. 常見錯誤:破壞 HTML 結構
接下來,我們在template目錄中建立一個home.html文件,並使用 Thymeleaf 表達式來顯示title和subtitle :
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
</head>
<body>
<h1 th:text="${title}" >
title
<small th:text="${subtitle}" >subtitle</small>
</h1>
</body>
</html>
在上面的程式碼中,我們嘗試在<h1>元素內同時渲染標題和副標題模型屬性。副標題被包裹在<small>標籤中,以便在視覺上與主標題區分開來。
乍一看,這種方法似乎很完美。然而,當我們編譯應用程式並訪問 URL – http://localhost:8080/home-page查看結果時,卻發現了一個意想不到的結果:
在上圖中, Thymeleaf 只渲染了標題而省略了副標題,因為將th:text=”${title}”表達式應用於<h1>元素會導致 Thymeleaf 刪除<h1>元素內的所有內容,包括包含副標題的<small>標籤。因此,最終的 HTML 程式碼中只渲染了標題。
4. 使用th:inline='text'
為了避免破壞 HTML 結構,我們可以使用 Thymeleaf 的文字內聯功能,將動態值直接渲染到元素的 body 內部。
讓我們透過重寫 HTML 程式碼的 body 部分來示範:
<body>
<h1 th:inline="text" >
[[${title}]]
<small th:text="${subtitle}">subtitle</small>
</h1>
</body>
這裡,我們透過在<h1>元素中加入th:inline=”text”來明確啟用文字內聯。這樣我們就可以使用[[ …]]內聯表達式語法將title的值直接插入到元素的內容中。
值得注意的是,當 Thymeleaf 以 HTML 模式處理範本時,文字內聯預設為啟用。因此,我們可以使用[[…]]內聯表達式,而無需在元素上明確聲明th:inline=”text” :
<body>
<h1>
[[${title}]]
<small th:text="${subtitle}">subtitle</small>
</h1>
</body>
但是,在腳本或樣式標籤內進行操作時,需要明確內聯,並且必須指定處理模式。
這是渲染後的新頁面:
在上圖中, title和subtitle都正確渲染了。這是因為標題使用了內嵌表達式進行渲染,這樣可以保留周圍的 HTML 結構,防止副標題被省略。
5. 透過在子元素中渲染文字來保持 HTML 結構
或者,我們可以透過將th:text應用於子元素而不是父元素<h1>來解決這個問題。這種方法可以保持 HTML 結構,並防止子元素被刪除:
<body>
<h1>
<span th:text="${title}" th:remove="tag">title</span>
<small th:text="${subtitle}" >subtitle</small>
</h1>
</body>
這裡,我們將title包裹在<span> ` 元素中。由於th:text只會取代 `` 元素的內容,因此不會影響<h1>元素的子節點。所以,副標題保持不變。
` th:remove=”tag”屬性是可選的,用於在 Thymeleaf 解析完<span>元素的內容後將其移除。這樣既能保持最終渲染的 HTML 程式碼簡潔,又能避免原有的結構問題。
如果我們檢查渲染後的 HTML,會得到以下輸出:
<body>
<h1>
Introduction to Java
<small >[Java powers over 1 billion devices]</small>
</h1>
</body>
這裡,**由於使用了th:remove=”tag”屬性,` <span>元素會從最終輸出中移除**。 Thymeleaf 會解析<span>的內容,然後移除元素本身,只保留其文字。
如果省略th:remove=”tag” ,則渲染的 HTML 仍將包含<span>元素,儘管兩種情況下頁面都會正確渲染。
6. 結論
本文介紹了在使用 Thymeleaf 模板引擎時可能無意中破壞 HTML 結構的常見陷阱。此外,我們也示範如何透過使用 Thymeleaf 的 ` th:inline=”text”屬性或在子元素中渲染動態文字來解決該錯誤。這兩種方法都允許我們在保留預期 HTML 標記的同時渲染動態內容。
與往常一樣,該範例的完整原始程式碼可在 GitHub 上找到。