You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在nwjs应用中通过文本选中实现不修改DOM的搜索高亮效果

不修改DOM实现关键词高亮(文本选中方案)

该方案完全不会修改原DOM结构,适配所有nwjs新版本的内核环境

实现核心思路

利用浏览器原生的Selection、Range以及CSS自定义高亮API实现关键词高亮,全程不会修改原有DOM节点,完全满足你的需求。

具体实现方案

基础版:单/多关键词统一高亮

原生Selection API支持通过JS批量添加选区,实现所有匹配关键词同时高亮的效果:

  • 递归遍历页面所有可视文本节点,排除script、style等不可见节点的内容,避免匹配到无关文本
  • 匹配到目标关键词的位置后,为每一处匹配结果创建独立的Range对象,绑定对应文本节点的起止偏移量
  • 全局选区实例批量添加所有Range,即可实现全部匹配结果的高亮显示

代码示例

// 高亮指定关键词
function highlightKeywords(keyword) {
  const selection = window.getSelection()
  // 清空之前的高亮
  selection.removeAllRanges()
  if (!keyword.trim()) return

  // 递归遍历文本节点匹配关键词
  function traverseNodes(node) {
    const childNodes = node.childNodes
    for (let i = 0; i < childNodes.length; i++) {
      const current = childNodes[i]
      // 处理文本节点
      if (current.nodeType === Node.TEXT_NODE && current.parentElement.offsetParent !== null) {
        const text = current.textContent
        let startPos = 0
        // 匹配所有关键词位置
        while (startPos < text.length) {
          const matchIndex = text.indexOf(keyword, startPos)
          if (matchIndex === -1) break
          // 创建选区范围
          const range = document.createRange()
          range.setStart(current, matchIndex)
          range.setEnd(current, matchIndex + keyword.length)
          selection.addRange(range)
          startPos = matchIndex + keyword.length
        }
      } 
      // 递归遍历普通元素节点
      else if (current.nodeType === Node.ELEMENT_NODE && !['SCRIPT','STYLE','IFRAME'].includes(current.tagName)) {
        traverseNodes(current)
      }
    }
  }
  // 可替换为你需要搜索的指定容器,不需要遍历整个body提升性能
  traverseNodes(document.body)
}

// 清空所有高亮
function clearHighlight() {
  window.getSelection().removeAllRanges()
}

如果需要修改默认的选中高亮样式,在全局CSS中添加如下配置即可:

::selection {
  background-color: #ffeb3b;
  color: #000;
}

进阶版:多关键词不同颜色高亮

如果需要同时匹配多个关键词,不同关键词显示不同高亮颜色,可以使用Chromium内核支持的CSS自定义高亮API,同样不会修改DOM:

代码示例

  1. 先添加全局CSS配置不同关键词的高亮样式:
::highlight(keyword-type-1) {
  background-color: #ffeb3b;
  color: #000;
}
::highlight(keyword-type-2) {
  background-color: #4caf50;
  color: #fff;
}
::highlight(keyword-type-3) {
  background-color: #f44336;
  color: #fff;
}
  1. JS逻辑实现:
function highlightMultiKeywords(keywordList) {
  // 清空之前的自定义高亮
  CSS.highlights.clear()
  if (!Array.isArray(keywordList) || keywordList.length === 0) return

  keywordList.forEach((keyword, index) => {
    const matchRanges = []
    // 遍历文本节点匹配关键词
    function traverseNodes(node) {
      const childNodes = node.childNodes
      for (let i = 0; i < childNodes.length; i++) {
        const current = childNodes[i]
        if (current.nodeType === Node.TEXT_NODE && current.parentElement.offsetParent) {
          const text = current.textContent
          let startPos = 0
          while (startPos < text.length) {
            const matchIndex = text.indexOf(keyword, startPos)
            if (matchIndex === -1) break
            const range = document.createRange()
            range.setStart(current, matchIndex)
            range.setEnd(current, matchIndex + keyword.length)
            matchRanges.push(range)
            startPos = matchIndex + keyword.length
          }
        } else if (current.nodeType === Node.ELEMENT_NODE && !['SCRIPT','STYLE','IFRAME'].includes(current.tagName)) {
          traverseNodes(current)
        }
      }
    }
    traverseNodes(document.body)
    // 注册对应关键词的高亮样式
    CSS.highlights.set(`keyword-type-${index+1}`, new Highlight(...matchRanges))
  })
}

注意事项

  • 可以限定遍历的DOM容器范围,不需要遍历整个body,大幅提升大页面的搜索性能
  • 文本匹配逻辑可以根据需求调整为大小写不敏感、正则模糊匹配等,只需要修改对应匹配部分的代码即可
  • 如果页面存在可编辑区域,可以提前过滤可编辑节点,避免和用户手动选区产生冲突

内容的提问来源于stack exchange,提问作者Gustavo Novais

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 02:27:01