如何修改JavaScript代码,实现忽略大小写与重音的HTML搜索词高亮?
如何修改JavaScript代码,实现忽略大小写与重音的HTML搜索词高亮?
我明白你的问题啦——现在的代码能处理带重音的搜索词,但用户输入不带重音的版本时就失效了,核心问题在于判断逻辑和替换逻辑不一致:判断时你做了去重音处理,但替换的正则还是严格匹配原搜索词的字符,自然匹配不到带重音的文本内容。
解决思路
我们需要让替换用的正则也能忽略重音,同时保留原文本中的重音字符(只是给它套上<mark>标签)。具体来说:
- 把搜索词转换成「能匹配对应重音变体」的正则模式
- 用这个模式去匹配文本,并用原匹配内容(带重音的版本)来生成高亮标签
修改后的完整代码
const search = 'ener'; // 现在输入不带重音的词也能生效了 function escapeRegExp(s) { return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } // 生成忽略重音的正则模式:把基础字符映射到包含所有重音变体的字符集 function getAccentInsensitivePattern(q) { const accentMap = { a: '[aàáâãäå]', e: '[eèéêë]', i: '[iìíîï]', o: '[oòóôõö]', u: '[uùúûü]', c: '[cç]', n: '[nñ]', y: '[yýÿ]', s: '[sß]' // 可以根据需求补充更多语言的重音字符 }; // 先对搜索词做去重音、转小写处理 const normalizedQ = q.toLowerCase().normalize('NFD').replace(/\p{Diacritic}/gu, ''); // 把每个基础字符替换成对应的重音字符集,非映射字符直接转义 return normalizedQ.split('').map(char => accentMap[char] || escapeRegExp(char)).join(''); } function addMarks(liItem, q) { const normalizedText = liItem.textContent.toLowerCase().normalize('NFD').replace(/\p{Diacritic}/gu, ''); const normalizedQ = q.toLowerCase().normalize('NFD').replace(/\p{Diacritic}/gu, ''); // 先判断是否存在匹配 if (normalizedText.includes(normalizedQ)) { const pattern = getAccentInsensitivePattern(q); // 构造正则:匹配标签内的文本,并且忽略大小写 liItem.innerHTML = liItem.innerHTML.replace( new RegExp( `(>[^<>]*)(${pattern})([^<>]*<)`, 'gi' ), // 用$2引用匹配到的原文本内容(带重音),套上mark标签 '$1<mark>$2</mark>$3' ); } } for (const liItem of document.querySelectorAll('li')) { addMarks(liItem, search); }
<ul> <li> <article> <h2>Mot avec accent : <b>énergie</b></h2> <p>L'importance de l'<dfn>énergie</dfn> renouvelable ne cesse de croître dans le monde moderne.</p> </article> </li> <li> <article> <h2>Expression avec caractères spéciaux : <b>Ça va ?</b></h2> <p>En français, <dfn>ça va ?</dfn> est une façon courante de demander des nouvelles.</p> </article> </li> <li> <article> <h2>Proverbe français : <b>À cœur vaillant rien d'impossible</b></h2> <p>Ce proverbe met en avant la détermination face aux défis :À cœur vaillant rien d'impossible.</p> </article> </li> </ul>
关键修改点说明
- 新增
getAccentInsensitivePattern函数:这个函数会把搜索词的每个基础字符(比如e)转换成包含所有重音变体的字符集(比如[eèéêë]),这样正则就能匹配到文本中带重音的对应内容了。 - 替换逻辑调整:不再直接用原搜索词做匹配,而是用生成的重音无关模式,并且用
$2引用匹配到的原文本内容(保留重音),确保高亮的是文本里原本的带重音字符。 - 保持判断逻辑的一致性:判断时还是用去重音后的文本和搜索词对比,确保不会误判。
现在不管你输入éner还是ener,都能正确高亮文本中的éner部分啦!
备注:内容来源于stack exchange,提问作者Daniel Schreurs
相关产品推荐
相关产品推荐

