8.4 移除模版片段
回到示例应用,让我们再看看最后一版的产品列表模版:
<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></table>
这段代码作为模版还好,但如果是一个静态页面(当直接由浏览器打开,而不是由Thymeleaf处理时),就称不上是一个好的原型了。
为什么呢?因为,尽管浏览器完美地表示了,但是表格只有一行,这行还是假数据。作为原型,看起来不够真实······我们应当有多个产品,我们需要更多行。
那就让我们加一些:
<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"><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></table>
好的,现在我们有三行了。对原型来说,绝对比之前更好。但是······当我们用Thymeleaf处理的时候,会发生什么呢?
<table><tr><th>NAME</th><th>PRICE</th><th>IN STOCK</th><th>COMMENTS</th></tr><tr><td>Fresh Sweet Basil</td><td>4.99</td><td>yes</td><td><span>0</span> comment/s</td></tr><tr class="odd"><td>Italian Tomato</td><td>1.25</td><td>no</td><td><span>2</span> comment/s<a href="/gtvg/product/comments?prodId=2">view</a></td></tr><tr><td>Yellow Bell Pepper</td><td>2.50</td><td>yes</td><td><span>0</span> comment/s</td></tr><tr class="odd"><td>Old Cheddar</td><td>18.75</td><td>yes</td><td><span>1</span> comment/s<a href="/gtvg/product/comments?prodId=4">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></table>
最后两行是假数据!遍历只应用在第一行,所以后两行不应该出现。
我们需要在模版处理时移除那两行。让我们在第二、第三个<tr>标签上使用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>
模版处理后,正常显示:
<table><tr><th>NAME</th><th>PRICE</th><th>IN STOCK</th><th>COMMENTS</th></tr><tr><td>Fresh Sweet Basil</td><td>4.99</td><td>yes</td><td><span>0</span> comment/s</td></tr><tr class="odd"><td>Italian Tomato</td><td>1.25</td><td>no</td><td><span>2</span> comment/s<a href="/gtvg/product/comments?prodId=2">view</a></td></tr><tr><td>Yellow Bell Pepper</td><td>2.50</td><td>yes</td><td><span>0</span> comment/s</td></tr><tr class="odd"><td>Old Cheddar</td><td>18.75</td><td>yes</td><td><span>1</span> comment/s<a href="/gtvg/product/comments?prodId=4">view</a></td></tr></table>
那个属性里的all值是什么意思呢🤔?th:remove依据它的值,有五种表现形式:
all: 移除所在的标签和它的所有子节点。body: 不移除所在的标签,但是移除它的所有子节点。tag: 移除所在的标签,但是不移除它的子节点。all-but-first: 移除所在标签的第一个子节点之外的所有子节点。none: 什么也不做。这个值对动态求值有用。
值all-but-first有什么用?它让我们在原型设计的时候,可以保留某些th:remove="all":
<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属性接受任何的Thymeleaf标准表达式,只要它返回允许的字符串值(all,tag,body,all-but-first或者none)。
这意味着可以使用条件表达式,比如:
<a href="/something" th:remove="${condition}? tag : none">Link text not to be removed</a>
注意th:remove将null等同于none,所以下面的例子和上面的例子的结果相同:
<a href="/something" th:remove="${condition}? tag">Link text not to be removed</a>
在这种情况下,如果${condition}为false,会返回null,因此什么也不会做。
