本文详解如何在 Thymeleaf 模板中结合 HTML <table> 标签与 th:each,优雅实现「每行渲染两个数据项」的布局需求,避免常见误区(如误将 th:each 放在 <table> 上),并提供健壮、可维护的代码示例。
本文详解如何在 thymeleaf 模板中结合 html `
在 HTML 表格中按“每行两列”展示列表数据(例如图书或歌手信息)是一个典型但易出错的场景。许多开发者会错误地将 th:each 直接作用于 <table> 标签(如原代码所示),导致每个数据项生成一个独立表格,不仅语义错误、破坏 DOM 结构,更无法实现真正的多列布局。
正确思路是:让 <tr>(表格行)承担循环职责,并在每轮迭代中主动渲染当前项及其后一项(若存在)。这需要借助 Thymeleaf 的状态变量 iterStat 获取索引,并通过模运算(% 2 == 0)控制仅在偶数索引时创建新行,再用条件判断安全访问下一项。
以下是推荐的生产级实现:
<table class="vocalist-table"> <tr th:each="vocalist, iterStat : ${bookList}" th:if="${iterStat.index % 2 == 0}"> <!-- 第一列:当前项 --> <td class="book-cell"> <div class="bookdiv" th:id="'startButton-' + ${iterStat.index}"> <img src="images/ClosedBook.png" class="closeBook" alt="Closed book"/> <span class="bookName" th:text="${vocalist.vocaName}">Vocalist Name</span> </div> </td> <!-- 第二列:下一项目(仅当存在时渲染) --> <td class="book-cell" th:if="${iterStat.index + 1 < bookList.size()}"> <div class="bookdiv" th:id="'startButton-' + ${iterStat.index + 1}"> <img src="images/ClosedBook.png" class="closeBook" alt="Closed book"/> <span class="bookName" th:text="${bookList[iterStat.index + 1].vocaName}">Next Vocalist</span> </div> </td> </tr></table>
✅ 关键要点说明:
立即学习“前端免费学习笔记(深入)”;
⚠️ 注意事项:
该方案兼顾兼容性、可读性与健壮性,已在 Spring Boot + Thymeleaf 项目中稳定运行。如需扩展为三列或动态列数,只需调整模运算基数与 <td> 渲染逻辑即可。