高亮移除功能异常:删除高亮时连带文本内容一同被移除,求解决方案
问题修复方案
你的问题出在移除高亮时只处理了<mark>标签的第一个子节点,要是标签里有多个子节点(比如选中文本跨了原有元素节点,或者surroundContents生成的结构里包含多个节点),就会导致部分文本跟着标签一起被删掉。
直接修改点击事件里的移除逻辑就行,不用只取第一个子节点,把<mark>的所有子节点都替换到它的位置,再删除标签:
// Add event listeners for when user clicks on highlighted text on any element elements.forEach(function(element) { element.addEventListener("click", function(event) { if (event.target.tagName === "MARK") { let mark = event.target; // 把mark的所有子节点替换到mark的位置 mark.replaceWith(...mark.childNodes); } }); });
或者用循环迁移子节点的思路,兼容旧环境:
// Add event listeners for when user clicks on highlighted text on any element elements.forEach(function(element) { element.addEventListener("click", function(event) { if (event.target.tagName === "MARK") { let mark = event.target; // 循环移除所有子节点,直到mark为空 while (mark.firstChild) { mark.parentNode.insertBefore(mark.firstChild, mark); } mark.parentNode.removeChild(mark); } }); });
另外还可以优化高亮逻辑,避免重复高亮和提升性能:
// 用事件委托替代遍历所有元素,减少监听数量 document.addEventListener("mouseup", highlightText); document.addEventListener("touchend", highlightText); function highlightText() { let selection = window.getSelection(); let selectedText = selection.toString(); if (selectedText !== '') { let range = selection.getRangeAt(0); // 避免给已高亮的文本重复套mark标签 let existingMark = range.commonAncestorContainer.closest('mark'); if (!existingMark) { let newNode = document.createElement("mark"); range.surroundContents(newNode); } // 清除选区,防止重复触发高亮 selection.removeAllRanges(); } } // 事件委托处理mark点击移除 document.addEventListener("click", function(event) { if (event.target.tagName === "MARK") { event.target.replaceWith(...event.target.childNodes); } });
内容的提问来源于stack exchange,提问作者RGS
相关产品推荐
相关产品推荐

