Thymeleaf 中拼文本、生成链接、绑定 JavaScript 事件,是三个不同上下文。文本能正确显示,不代表同样的字符串拼接也适合放进 onclick;先使用对应的模板能力,再处理动态值。
文本拼接:加号或字面替换
假设 model 中有 name,可以写:
<p th:text="${'你好,' + name + '!'}">问候</p>
<p th:text="|你好,${name}!|">问候</p>
竖线包围的是字面替换,适合混合固定文案和变量;不是 JavaScript 模板字符串,也不要求为了显示一段固定文字而强行放入变量。Thymeleaf 字面替换
普通文本优先使用 th:text,保留 HTML 转义。th:utext 会输出未转义内容,不适合直接承接不可信输入。
链接:让链接表达式处理路径和参数
假设 item.id 是当前条目 ID:
<a th:href="@{/items/{id}(id=${item.id})}">查看详情</a>
<a th:href="@{/items(id=${item.id},mode='detail')}">查看列表项</a>
第一种是路径变量,第二种是查询参数。@{…} 负责生成应用链接,不要把 HTML 实体转义、URL 编码和 JavaScript 引号转义混作一件事。链接表达式
需要按钮事件时,先把数据放入属性
普通跳转尽量直接用链接。确实需要脚本处理时,可以避免动态拼出 onclick 源码:
<button type="button" class="edit-item"
th:attr="data-code=${item.code}">编辑</button>
然后在独立脚本或页面末尾绑定事件:
document.querySelectorAll(".edit-item").forEach(function (button) {
button.addEventListener("click", function () {
const code = button.dataset.code;
if (!code) return;
window.location.assign("/items/" + encodeURIComponent(code) + "/edit");
});
});
示例把 code 作为固定站内路径的一段编码;它不允许 code 决定协议或域名。后台仍需验证条目和操作权限。type=“button” 还能避免表单内按钮意外提交。
核对页面时同时检查最终 HTML、点击行为和带引号或特殊字符的数据。模板源码看起来闭合,不足以证明浏览器收到的属性与脚本仍是预期结构。