如何判断DOM元素相对顺序并找到选中文本前最后一个marker类span
解决方案
一、DOM节点相对顺序判断标准方案
原生DOM标准提供了Node.compareDocumentPosition()接口,可直接判断两个节点在文档流中的线性顺序,完全不受CSS样式影响,是DOM Level 2规范定义的通用标准,支持所有现代浏览器(IE9+)。
该方法返回位掩码结果,常用的判断规则:
nodeA.compareDocumentPosition(nodeB) & Node.DOCUMENT_POSITION_FOLLOWING返回真值时,说明nodeB在nodeA的文档顺序之后,即nodeA在nodeB之前。
二、找到锚点前最后一个.marker元素的实现
推荐使用原生document.createTreeWalker() API,它可以按文档顺序高效遍历指定根节点下符合筛选条件的所有节点,无需手动递归遍历DOM,性能和稳定性都远高于自定义遍历逻辑。
原生JavaScript实现
function getLastMarkerBeforeSelection() { const selection = window.getSelection(); // 无选中内容直接返回 if (!selection.rangeCount) return null; const anchorNode = selection.anchorNode; const container = document.querySelector('.container'); // 创建遍历器,仅筛选container下的span.marker元素 const treeWalker = document.createTreeWalker( container, NodeFilter.SHOW_ELEMENT, { acceptNode: node => node.tagName === 'SPAN' && node.classList.contains('marker') ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP } ); let lastMatch = null; let currentMarker; while (currentMarker = treeWalker.nextNode()) { // 判断当前marker是否在锚点之前 if (currentMarker.compareDocumentPosition(anchorNode) & Node.DOCUMENT_POSITION_FOLLOWING) { lastMatch = currentMarker; } else { // 按文档顺序遍历,遇到第一个在锚点后的marker即可提前终止,提升性能 break; } } return lastMatch; } // 使用示例 const targetMarker = getLastMarkerBeforeSelection(); console.log(targetMarker?.textContent); // 示例中输出Marker 1
jQuery实现
如果你项目中已经引入jQuery,也可以用更简洁的写法:
function getLastMarkerBeforeSelection() { const selection = window.getSelection(); if (!selection.rangeCount) return null; const anchorNode = selection.anchorNode; // 筛选所有符合条件的marker,过滤出在锚点之前的,取最后一个 return $('.container span.marker') .filter(function() { return this.compareDocumentPosition(anchorNode) & Node.DOCUMENT_POSITION_FOLLOWING; }) .last() .get(0); }
内容的提问来源于stack exchange,提问作者diwhyyyyy
相关产品推荐
相关产品推荐

