八、模板布局(Template Layout)
8.1 包含模板片段(Including template fragments)
定义和引用片段
我们通常想要从别的模板文件中调用一些模板片段,例如 页面的头部、底部和菜单...等
th:fragment
定义一个文件 /WEBINF/templates/footer.html
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-4.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <body> <div th:fragment="copy"> © 2011 The Good Thymes Virtual Grocery </div> </body> </html>
定义了个名为copy的片段,可以通过用th:include 和 th:replace 放到其他页面中
<body> <div th:include="footer::copy"></div> </body>
三种格式:
- "templatename::domselector" 或者 templatename::[domselector] ——包含名为templatename的domselector部分,英文原文:Includes the fragment resulting from executing the specified DOM Selector on the template named templatename .
- "templatename" ——包含外部模板文件的整个片段
- "::domselector"或者"this::domselector" ——包含来自自身模板文件的片段
templatename和domselector部分都可以是其他任何表达式(甚至是条件判断表达式)
<div th:include= "footer::(${user.isAdmin}? #{footer.admin}: #{footer.normaluser})"></div>
Referencing fragments(引用片段) without th:fragment
... <div id="copy-section"> © 2011 The Good Thymes Virtual Grocery </div> ...
通过id属性引用上面的片段
<body> ... <div th:include="footer:: #copy-section"></div> </body>
th:include和th:replace(也可写成th:substituteby)的区别
前者包含片段的内容到当前标签内,后者是用整个片段(内容和上一层)替换当前标签(不仅仅是标签内容)。
<footer th:fragment="copy"> © 2011 The Good Thymes Virtual Grocery </footer>
<body> ... <div th:include="footer :: copy"></div> <div th:replace="footer :: copy"></div> </body>
编译后:
<body> ... <div> © 2011 The Good Thymes Virtual Grocery </div> <footer> © 2011 The Good Thymes Virtual Grocery </footer> </body>
8.2 可带参数的片段标签(Parameterizable fragment signatures)
<div th:fragment="frag (onevar,twovar)"> <p th:text="${onevar}+' - ' +${twovar}">...</p> </div>
<div th:include="::frag(${value1},${value2})">...</div> <div th:include="::frag(onevar=${value1},twovalue=${vaule2})"></div> <div th:include="::frag(twovalue=${vaule2},onevar=${value1})"></div>
即使标签没有定义参数,like this:
<div th:fragment="frag"> ... </div>
我们还是可以用这句:
<div th:include="::frag(onevar=${value1},twovar=${value2})"></div> //等价于 th:include和th:with <div th:include="::frag" th:with="onevar=${value1},twovar=${value2}"></div>
Note that this specification of local variables for a fragment —no matter whether it has a signature or not— does not cause the context to emptied previously to its execution. Fragments will still be able to access every context variable being used at the calling template like they currently are.
th:assert for in-template assertions
<div th:assert="${onevar},(${twovar} !=43)">...</div>
要验证参数时会派上用场
<header th:fragment="contentheader(title)" th:assert="${!#string.isEmpty(title)}">...</header>
8.3 移除模板标签(Removing template fragments)
th:remove
<table> <tr> <th>NAME</th> <th>PRICE</th> <th>IN STOCK</th> <th>COMMENTS</th> </tr> <tr th:each="prod : ${prods}" th:class="${prodStat.odd}? 'odd'"> <td th:text="${prod.name}">Onions</td> <td th:text="${prod.price}">2.41</td> <td th:text="${prod.inStock}? #{true} : #{false}">yes</td> <td> <span th:text="${#lists.size(prod.comments)}">2</span> comment/s <a href="comments.html" th:href="@{/product/comments(prodId=${prod.id})}" th:unless="${#lists.isEmpty(prod.comments)}">view</a> </td> </tr> <tr class="odd" th:remove="all"> <td>Blue Lettuce</td> <td>9.55</td> <td>no</td> <td> <span>0</span> comment/s </td> </tr> <tr th:remove="all"> <td>Mild Cinnamon</td> <td>1.99</td> <td>yes</td> <td> <span>3</span> comment/s <a href="comments.html">view</a> </td> </tr> </table>
th:remove="all" ——移除整个元素包括全部子元素
th:remove="body" ——不移除本身标签元素,移除全部子元素
th:remove="tag" ——只移除本身标签元素,子元素还存在的
th:remove="all-but-first" ——移除所有子元素除了第一个子元素
th:remove="none" 不做任何移除
我们来看一个all-but-first的应用场景:
<table> <thead> <tr> <th>NAME</th> <th>PRICE</th> <th>IN STOCK</th> <th>COMMENTS</th> </tr> </thead> <tbody th:remove="all-but-first"> <tr th:each="prod : ${prods}" th:class="${prodStat.odd}? 'odd'"> <td th:text="${prod.name}">Onions</td> <td th:text="${prod.price}">2.41</td> <td th:text="${prod.inStock}? #{true} : #{false}">yes</td> <td> <span th:text="${#lists.size(prod.comments)}">2</span> comment/s <a href="comments.html" th:href="@{/product/comments(prodId=${prod.id})}" th:unless="${#lists.isEmpty(prod.comments)}">view</a> </td> </tr> <tr class="odd"> <td>Blue Lettuce</td> <td>9.55</td> <td>no</td> <td> <span>0</span> comment/s </td> </tr> <tr> <td>Mild Cinnamon</td> <td>1.99</td> <td>yes</td> <td> <span>3</span> comment/s <a href="comments.html">view</a> </td> </tr> </tbody> </table>
th:remove后面也可以是表达式,只要是返回 ( all , tag , body , all-but-first , none )中的任意一个;th:remove把null看成none,所以也可以返回为null值,所以下面两句话一样。
<a href="/something" th:remove="${condition}? tag">Link text not to be removed</a>
<a href="/something" th:remove="${condition}? tag : none">Link text not to be removed</a>