如何在WKWebView网页中查找并高亮标签间文本,实现浏览器查找功能
iOS WKWebView 文本搜索高亮实现方案
原代码失效根因
- iOS端WKWebView内核限制了
document.execCommand编辑类接口的使用,BackColor、HiliteColor等命令均无法生效 window.find在移动端WebKit中存在行为兼容问题,无法稳定匹配跨HTML标签的连续文本document.designMode切换在WKWebView中会触发未知渲染异常,无法实现预期效果
兼容实现方案
放弃依赖浏览器原生编辑命令,改用DOM节点遍历、手动包裹高亮标签的方案,该方案完全兼容WKWebView,同时天然支持跨标签文本匹配,完整可运行代码如下:
<!DOCTYPE html> <html> <head> <title>WKWebView 文本高亮测试页</title> <style> /* 可自定义高亮样式 */ .search-highlight { background-color: #ff0; font-weight: inherit; } </style> </head> <body> <input type="text" id="search" autofocus onkeyup="highlight(this.value);" /> <div id="content"> <p>Here is some searchable <b>text</b> with some lápices in it, and more lápices, and some <b>for<i>mat</i>t</b>ing</p> </div> <script type="text/javascript"> // 移除所有已有高亮,还原原生DOM结构 function unhighlight() { const highlights = document.querySelectorAll('.search-highlight'); highlights.forEach(highlight => { const parent = highlight.parentNode; parent.replaceChild(document.createTextNode(highlight.textContent), highlight); parent.normalize(); }); } // 递归获取节点下所有文本节点 function getTextNodes(node) { const textNodes = []; if (node.nodeType === Node.TEXT_NODE) { textNodes.push(node); } else { for (let i = 0; i < node.childNodes.length; i++) { textNodes.push(...getTextNodes(node.childNodes[i])); } } return textNodes; } // 高亮匹配的搜索词 function highlight(searchText, caseSensitive = false) { unhighlight(); const trimText = searchText.trim(); if (!trimText) return; const flags = caseSensitive ? 'g' : 'gi'; // 转义正则特殊字符 const escapedText = trimText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); const regex = new RegExp(escapedText, flags); const textNodes = getTextNodes(document.body); textNodes.forEach(node => { if (!regex.test(node.textContent)) return; let lastIndex = 0; const fragment = document.createDocumentFragment(); node.textContent.replace(regex, (match, index) => { if (index > lastIndex) { fragment.appendChild(document.createTextNode(node.textContent.slice(lastIndex, index))); } const highlightSpan = document.createElement('span'); highlightSpan.className = 'search-highlight'; highlightSpan.textContent = match; fragment.appendChild(highlightSpan); lastIndex = index + match.length; }); if (lastIndex < node.textContent.length) { fragment.appendChild(document.createTextNode(node.textContent.slice(lastIndex))); } node.parentNode.replaceChild(fragment, node); }); } </script> </body> </html>
方案优势
- 不依赖任何浏览器私有接口,全版本iOS WKWebView均可正常运行
- 不会修改原页面的DOM结构逻辑,清除高亮后完全还原初始页面状态
- 支持特殊字符、中文、带重音符号的字符匹配,可通过参数自定义是否大小写敏感
内容的提问来源于stack exchange,提问作者Prince
相关产品推荐
相关产品推荐

