Thymeleaf 3.1中th:include迁移至th:insert的问题解决
Thymeleaf 3.1 替换 th:include 后表头渲染异常的解决方法
在 Thymeleaf 3.1 版本中,th:include 已被弃用,替换为推荐的 th:insert 后,出现了两个棘手问题:原 <th> 上的自定义样式无法生效,同时渲染出多余的空 <th> 标签,完全无法复现原 th:include 的效果。
原代码与问题现象
原 home.html 代码(使用 th:include):
<table> <thead> <tr> <th scope="col" th:include="~{components/tableheader :: tableheader('test')}" style="text-align:right"/> </tr> </thead> </table>
原片段 components/tableheader.html:
<html xmlns="http://www.w3.org/1999/html" xmlns:th="http://www.thymeleaf.org"> <th scope="col" th:fragment="tableheader(text)"> <div th:text="${text}"/> <!-- other stuff--> </th> </html>
替换为 th:insert 后的异常渲染结果:
<table> <thead> <tr> <th scope="col" style="text-align:right"></th> <!-- 多余空元素 --> <th scope="col"> <div>test</div> </th> </tr> </thead> </table>
核心原因
th:include 的逻辑是将片段中目标元素的内容插入到当前元素内部,相当于保留当前 <th> 的所有属性,仅把片段里 <th> 的内容填充进来;而 th:insert 的逻辑是将整个片段元素插入到当前元素内部,所以原 <th> 会被保留为空容器,片段里的 <th> 会作为子元素插入进去,最终生成两个 <th> 标签。
解决方案
方案1:修改片段为仅包含内部内容(最简便)
将片段中的 <th> 替换为 <th:block>(Thymeleaf 的无渲染容器标签),只保留表头的内部内容:
<!-- components/tableheader.html 修改后 --> <html xmlns="http://www.w3.org/1999/html" xmlns:th="http://www.thymeleaf.org"> <th:block th:fragment="tableheader(text)"> <div th:text="${text}"/> <!-- other stuff--> </th:block> </html>
home.html 中仍使用 th:insert,此时片段内容会直接插入到原 <th> 内部,保留原 <th> 的样式和属性:
<table> <thead> <tr> <th scope="col" th:insert="~{components/tableheader :: tableheader('test')}" style="text-align:right"/> </tr> </thead> </table>
渲染结果会和原 th:include 完全一致:
<table> <thead> <tr> <th scope="col" style="text-align:right"> <div>test</div> </th> </tr> </thead> </table>
方案2:使用 th:replace + 属性传递
如果需要保留片段中的 <th> 结构,可以改用 th:replace(直接替换当前元素),并将样式作为参数传递给片段:
<!-- components/tableheader.html 修改后 --> <html xmlns="http://www.w3.org/1999/html" xmlns:th="http://www.thymeleaf.org"> <th scope="col" th:fragment="tableheader(text, headerStyle)" th:style="${headerStyle}"> <div th:text="${text}"/> <!-- other stuff--> </th> </html>
home.html 中调用时传递样式参数:
<table> <thead> <tr> <th th:replace="~{components/tableheader :: tableheader('test', 'text-align:right')}"/> </tr> </thead> </table>
这种方式会直接用片段中的 <th> 替换原 <th>,同时应用传递的样式,也不会生成多余元素。
内容的提问来源于stack exchange,提问作者membersound
相关产品推荐
相关产品推荐

