必须在templet函数中手动提取纯文本、转义关键词、正则替换并包裹,否则会破坏html结构或引发xss风险。

不能靠 table.reload() 自动触发高亮,必须在列的 templet 函数里手动提取纯文本、转义关键词、正则替换并包裹 <span class="layui-table-keyword"></span>,否则会破坏 HTML 结构或引入 XSS 风险。
templet 里直接用 replace() 为什么炸了
常见错误是写成 d.title.replace(keyword, '<span class="highlight">$</span>'),结果页面错乱、控制台报错或点开标签页弹窗。原因有四个:
- 关键词含
.、*、(等正则元字符时,replace()把它当正则执行,直接抛Invalid regular expression - 单元格内容本身带 HTML(比如
<div data-id="admin">xxx</div>),replace()会把data-id里的字符也匹配进去,导致标签截断 - 用户输入
<script>alert(1)</script>,没转义就拼进 DOM,等于白送 XSS 入口 -
templet渲染时机早于搜索框 DOM 更新,$('#keyword').val()拿到的是旧值,高亮永远滞后一拍
怎么安全提取纯文本再高亮
核心是剥离 HTML 标签,只对用户真正看到的文字做操作。Layui 不提供现成方法,得自己动手:
- 用
layui.$('<div>' + d.title + '</div>').text()提取纯文本——比正则更稳,能处理嵌套、自闭合、属性等复杂情况 - 手动补正则转义:
const escaped = keyword.replace(/[.*+?^${}()|[]\]/g, '\$&')(注意方括号里要双反斜杠) - 构造正则:
new RegExp('(' + escaped + ')', 'gi'),必须加g和i - 替换后用
layui.$('<div>' + highlighted + '</div>').html()转回字符串,确保只输出<span></span>,不带额外标签
搜索后高亮不更新?reload 是唯一可靠路径
templet 只在 table.render() 初始渲染或 table.reload() 时执行,不会监听 input 变化。你改了搜索词,表格还是旧的——这是最常卡住人的点。
- 别在
templet里实时读$('#keyword').val():DOM 还没更新,拿到的是上一次的值 - 必须在搜索事件(如按钮
click或input的防抖回调)里调用table.reload() -
reload()必须传where: { keyword: val },且显式带page: { curr: 1 },否则翻页状态下搜不到数据 - 关键词来源统一从
opts.where?.keyword取,避免全局变量不同步;多字段复用时抽成公共函数highlight(text, keyword)
CSS 没生效?不是代码问题,是权重和选择器写错了
Layui 不带默认高亮样式,.layui-table-keyword 是你自定义的类名,没加 CSS 就等于没写代码。
- 推荐写法:
.layui-table tbody td .layui-table-keyword { background-color: #ffd850; padding: 0 4px; border-radius: 2px; } - 如果用了
skin: 'line',td默认有透明背景,background-color可能被盖住,加!important更稳 - 别用
.highlight这种泛命名,容易被其他组件样式污染;优先用带上下文的选择器,比如.layui-table .layui-table-keyword - 真正容易漏的是 reload 时没重置页码,还有 CSS 选择器被表格皮肤样式压掉——这两处一出问题,整个高亮就静默失效











