列表搜索时怎么实现高亮匹配的关键词?

Tr° 郭云 阅读 9

我在做一个用户列表的搜索功能,输入关键词后能过滤出匹配的项,但不知道怎么把匹配的文字高亮显示出来。试过直接用 innerHTML 插入带 <mark> 标签的字符串,但感觉不太安全,而且 Vue 里还报警告。

有没有更稳妥的做法?比如在渲染的时候动态包裹匹配部分?下面是我现在的过滤逻辑:

const filteredUsers = users.filter(user =>
  user.name.toLowerCase().includes(searchTerm.toLowerCase())
);
我来解答 赞 1 收藏
二维码
手机扫码查看
1 条解答
Air-珍珍
这个问题我之前也踩过坑,说下我的做法。

最稳妥的方式是把匹配的文字拆分开,用 Vue 的 v-for 来分别渲染匹配和非匹配的部分,这样完全不需要 v-html,避免 XSS 风险:

先写个辅助函数,把文本按关键词拆成数组:

function splitByKeyword(text, keyword) {
if (!keyword) return [{ text, highlight: false }]

const regex = new RegExp((${keyword}), 'gi')
const parts = text.split(regex)

return parts.map(part => ({
text: part,
highlight: part.toLowerCase() === keyword.toLowerCase()
}))
}


然后在模板里这样用:





这样拆分后渲染,匹配到的文字会带上 highlight 类,没匹配的就是普通文本。

如果你非要用 v-html 也不是不行,但一定要先对原文本做 HTML 转义,再替换关键词:

function highlightSafe(text, keyword) {
if (!keyword) return text

// 先转义 HTML 特殊字符
const escaped = text
.replace(/&/g, '&')
.replace(/ .replace(/>/g, '>')

// 再替换关键词
const regex = new RegExp((${keyword}), 'gi')
return escaped.replace(regex, '$1')
}


不过说实话,第一种拆分渲染的方式更干净,不用担心 XSS 问题,也不会有 Vue 的警告。我现在项目里用的都是第一种。
点赞 1
2026-03-11 18:02