数字马力251028 | 文本高亮

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
  </head>
  <body>
    <div id="jsContent">
      <span>hhhhh前端开发发发发发前端开发+</span>
      highlight test 前端前端开发
      <span>发前发</span>
    </div>
    <script>
      // 1、分析A节点的内容,高亮给定的的关键词,高亮方式为用<em>标签包裹
      // 2、同一字符串中,优先匹配最长的关键词,且同一字符串只需高亮一次
      // 例如:关键词test,字符串“tttesttest”中应高亮第一个“test”
      // 3、不能跨标签高亮
      // 4、关键词可能包含特殊字符,如“+”、“*”等
      function highlight(word) {
        if (!word) return;

        const container = document.getElementById("jsContent");
        if (!container) return;

        // 高亮实现
        function processNode(node, keywords) {
          // 如果是文本节点
          if (node.nodeType === Node.TEXT_NODE) {
            let text = node.textContent;
            let lastIndex = 0;
            let fragments = [];
            let matched = false;

            // 逐一匹配关键词
            for (let i = 0; i < keywords.length; i++) {
              const keyword = keywords[i];
              //构造相应的正则表达式,注意转义特殊字符
              const regex = new RegExp(
                keyword.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"),
                "g"
              );
              let match;

              if ((match = regex.exec(text))) {
                matched = true;
                // 添加匹配前的文本
                if (match.index > lastIndex) {
                  fragments.push(text.substring(lastIndex, match.index));
                }
                // 添加高亮文本
                const em = document.createElement("em");
                em.textContent = match[0];
                fragments.push(em);
                lastIndex = match.index + match[0].length;
                // 添加剩余文本
                if (lastIndex < text.length) {
                  fragments.push(text.substring(lastIndex));
                }
              }

              if (matched) break;
            }
            // 如果有匹配,替换原节点
            if (fragments.length > 0) {
              //   const parent = node.parentNode;
              //   fragments.forEach((fragment) => {
              //     parent.insertBefore(
              //       typeof fragment === "string"
              //         ? document.createTextNode(fragment)
              //         : fragment,
              //       node
              //     );
              //   });
              //   parent.removeChild(node);
			  // (以下方式更优
              const fragment = document.createDocumentFragment();
              for (let item of fragments) {
                if (typeof item === "string") {
                  fragment.appendChild(document.createTextNode(item));
                } else {
                  fragment.appendChild(item);
                }
              }
              node.parentNode.replaceChild(fragment, node);
            }
            }
          } else if (
            node.nodeType === Node.ELEMENT_NODE &&
            node.nodeName !== "EM"
          ) {
            // 递归处理子节点(跳过em标签)
            const children = Array.from(node.childNodes);
            for (let child of children) {
              processNode(child, [...keywords]); // 传递keywords的副本
            }
          }
        }

        // 生成所有需要匹配的关键词(从长到短排序)
        const keywords = [];
        for (let i = word.length; i > 0; i--) {
          keywords.push(word.substring(0, i));
        }
        // 开始处理
        processNode(container, keywords);
      }
      highlight("前端开发");
    </script>
  </body>
</html>

全部评论

相关推荐

10-24 01:06
不想上班的喜羊羊很不...:查个🥚,你都进大厂了,肯定看你技术啊,谁管你30,50的,只有选调,公务员这种是会相当严格背调的,所以把心放肚子里吧兄弟
点赞 评论 收藏
分享
帮你内推|数字马力(长沙)信息技术有限公司 校招
点赞 评论 收藏
分享
天门一键开:她的意思是问你有没有论文吧
点赞 评论 收藏
分享
评论
1
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务