Vue实现搜索匹配内容加粗 含特殊连字符、撇号的处理方案
核心问题
现有实现的高亮匹配逻辑没有和筛选逻辑保持一致的特殊字符忽略规则,直接在原始字符串中搜索原始输入,无法命中包含连字符、撇号、空格的片段。
解决方案
1. 统一预处理规则
首先修正原有筛选逻辑的字符替换写法,原replaceAll("-'", "")仅能替换连续的-'组合,改为正则匹配移除所有-、'、空格三类字符,和需求中的输入场景对齐。
2. 双指针定位匹配片段
改造makeBold方法,通过双指针遍历原始城市名,定位到和预处理后输入匹配的完整片段(包含中间的特殊字符),再对该片段做高亮处理。
完整代码实现
筛选逻辑修改
computed: { results() { // 预处理输入:移除-、'、空格,转小写 const cleanSearch = this.searchInput.replace(/[-'\s]/g, '').toLowerCase() if (!cleanSearch) return [] // 无输入时可根据需求调整返回逻辑 return this.options.filter((option) => option.display_name .replace(/[-'\s]/g, '') .toLowerCase() .includes(cleanSearch) ) }, },
高亮方法改造
methods: { makeBold(str, query) { // 预处理查询词:移除-、'、空格,转大写 const cleanQuery = query.replace(/[-'\s]/g, '').toUpperCase() if (!cleanQuery) return str const strLength = str.length const queryLength = cleanQuery.length let queryPointer = 0 let matchStart = -1 let matchEnd = -1 // 遍历原始字符串定位匹配片段起止位置 for (let i = 0; i < strLength; i++) { const currentChar = str[i].replace(/[-'\s]/g, '').toUpperCase() // 跳过无意义的特殊字符 if (!currentChar) continue if (currentChar === cleanQuery[queryPointer]) { // 记录匹配起始位置 if (queryPointer === 0) matchStart = i queryPointer++ // 全量匹配完成,记录结束位置终止遍历 if (queryPointer === queryLength) { matchEnd = i break } } else if (queryPointer > 0) { // 匹配中断重置指针 queryPointer = 0 matchStart = -1 } } // 无匹配返回原字符串 if (matchStart === -1 || matchEnd === -1) return str // 拼接高亮结果 return ( str.slice(0, matchStart) + '<b><u>' + str.slice(matchStart, matchEnd + 1) + '</u></b>' + str.slice(matchEnd + 1) ) }, }
注意事项
模板中渲染高亮结果时需要使用v-html指令,否则HTML标签会被转义为普通文本,示例用法:
<li v-for="option in results" :key="option.value" v-html="makeBold(option.display_name, searchInput)"></li>
该实现可完全兼容需求中的三类输入场景:sint j、sintj、Sint-j,都会正确高亮城市名中对应的Sint-J片段。
内容的提问来源于stack exchange,提问作者Thore。
相关产品推荐
相关产品推荐

