直接在templet中用replace替换关键词会导致HTML结构损坏、正则报错、XSS漏洞及标签污染;正确做法是先剥离HTML取纯文本,转义关键词后正则高亮,再安全注入DOM。
templet 里直接替换关键词会出什么问题
直接用 d.title.replace(keyword, '<span style="color:red;">' + keyword + '</span>') 看似简单,但实际踩坑极多:
- 匹配到 HTML 属性里(比如
<div data-id="admin"> 中的 <code>admin),导致 DOM 结构损坏 - 关键词含正则特殊字符(如
.、*、()时,replace()当作正则执行,报错或误替换 - 未转义用户输入,若 keyword 是
<script>alert(1)</script>,直接拼进 HTML 就是 XSS - 单元格内容本身含 HTML 标签(如富文本字段),
replace()会污染标签结构,渲染异常 - 用正则
/>([^ 或 <code>layui.$('<div>' + d.content + '</div>').text()提取纯文本(推荐后者,更稳) - 关键词需转义:自己补一个
RegExp.escape = s => s.replace(/[.*+?^${}()|[]\]/g, '\$&') - 构造正则时加
g和i标志,确保全局、忽略大小写匹配 - 替换后用
layui.$('<div>' + highlightedText + '</div>').html()输出,避免脚本执行
安全提取纯文本再高亮的正确流程
必须先剥离 HTML,只对可见文本做匹配和包裹,再塞回 DOM。Layui 没提供现成方法,得手动处理:
示例片段(放在 templet 函数内):
templet: function(d) {
var keyword = $('#input_id_keyword').val().trim();
if (!keyword) return d.title;
var text = layui.$('<div>' + d.title + '</div>').text(); // 安全取纯文本
var escaped = RegExp.escape(keyword);
var reg = new RegExp('(' + escaped + ')', 'gi');
var highlighted = text.replace(reg, '<span style="color:red;">$1</span>');
return layui.$('<div>' + highlighted + '</div>').html();
}
搜索触发后如何让高亮同步更新
Layui 表格原生不监听搜索框变化,高亮不会自动刷新——你改了输入框,表格还是旧的 templet 渲染结果。
- 必须在搜索按钮或
keyup事件里调用table.reload(),并传入当前 keyword 到where -
reload()时要显式带上page: { curr: 1 },否则页码不变,可能搜不到数据 - 如果想“边输边搜”,用
layui.$('#keyword').on('input', ...),但注意防抖,避免频繁 reload - 别把 keyword 存在全局变量里靠
templet读——reload 后templet才执行,此时变量可能已变,容易不同步
CSS 样式和性能要注意什么
高亮样式不能只靠内联 style,否则大量单元格重复渲染影响性能,且难统一维护:
- 在页面 head 里加统一 CSS:
.highlight-keyword { color: red; font-weight: bold; } - 替换时用
<span class="highlight-keyword">$1</span>,而非内联样式 - 如果表格列多、行数大(比如 >500 行),templet 里做正则替换会卡顿——考虑只对当前页、且仅当 keyword 非空时才高亮,其他情况直返原始值
- 移动端要注意
span套嵌过深导致文字折行异常,可加white-space: nowrap;或限制高亮最多 3 处
真正麻烦的不是怎么写高亮,而是每次 reload 都要重新提取、转义、正则、包裹、再 html —— 这些操作在每行每列都发生,稍不注意就拖慢整个表格响应。别省那几行代码,该抽函数抽函数,该加节流加节流。











