获取从一个节点到另一个节点的 DOM 路径

Get DOM path from a node to another

本文关键字:节点 另一个 DOM 路径 一个 获取      更新时间:2023-09-26

我需要一种方法,该方法作为参数两个节点(node1node2(,返回从node1 node2的最小路径。理想情况下,它返回一个节点数组,但目前对字符串是可以的。所以例如:

        P
      /   '
  #text    U
         /   '
        B     I
        |     |
     #text   #text
function foo(node1, node2) {
    ...
}

当我以这种方式运行时,例如在节点P(根(和B

var res = foo(P, B);
console.log(res);

我获得:

res = Array[3] {
    0: P (class=..., id=...)
    1: U (class=..., id=...)
    2: B (class=..., id=...)
}

或者,以字符串的形式:

res = "P(class=..., id=...) > U(class=..., id=...) > B(class=..., id=...)";

如果节点具有属性(例如 idclass (,则甚至返回这些属性(如示例中所示(。我搜索了做类似事情的互联网方法,但我只找到了返回整个文档的完整路径而不是两个节点之间的方法。例如,我试过这种方法对我不起作用,因为它返回单个节点的完整路径。

function getDomPath(el) {
  var stack = [];
  while ( el.parentNode != null ) {
    console.log(el.nodeName);
    var sibCount = 0;
    var sibIndex = 0;
    for ( var i = 0; i < el.parentNode.childNodes.length; i++ ) {
      var sib = el.parentNode.childNodes[i];
      if ( sib.nodeName == el.nodeName ) {
        if ( sib === el ) {
          sibIndex = sibCount;
        }
        sibCount++;
      }
    }
    if ( el.hasAttribute('id') && el.id != '' ) {
      stack.unshift(el.nodeName.toLowerCase() + '#' + el.id);
    } else if ( sibCount > 1 ) {
      stack.unshift(el.nodeName.toLowerCase() + ':eq(' + sibIndex + ')');
    } else {
      stack.unshift(el.nodeName.toLowerCase());
    }
    el = el.parentNode;
  }
  return stack.slice(1); // removes the html element
}

另一件事,我会使用纯JavaScript,而不是jQuery。我不知道如何做我需要的,您的帮助将不胜感激。

谢谢

<!DOCTYPE html>
<html>
<script>
window.onload = function() {
    console.log(min_path(
        document.getElementById("4"),
        document.getElementById("9")
    ));
};
function min_path(node1, node2) {
    if(node1 === node2) {
        return node1;
    }
    var node_1_ancestors = get_ancestors(node1);
    var node_2_ancestors = get_ancestors(node2);
    var divergent_index = 0;
    while(node_1_ancestors[divergent_index] === node_2_ancestors[divergent_index]) {
        divergent_index++;
    }
    var path = [];
    for(var i = node_1_ancestors.length - 1; i >= divergent_index - 1; i--) {
        path.push(node_1_ancestors[i]);
    }
    for(var i = divergent_index; i < node_2_ancestors.length; i++) {
        path.push(node_2_ancestors[i]);
    }
    return path;
}
function get_ancestors(node) {
    var ancestors = [node];
    while(ancestors[0] !== null) {
        ancestors.unshift(ancestors[0].parentElement);
    }
    return ancestors;
}
</script>
</head>
<body>
<div id="0">
    <div id="1">
        <div id="2">
            <span id="3"></span>
            <span id="4">node1</span>
        </div>
        <div id="5">
            <p id="6"></p>
            <span id="7">
                <div id="8">
                    <div id="9">node2</div>
                    <div id="10"></div>
                </div>
            </span>
        </div>  
    </div>
    <div id="11"></div>
</div>
</body>
</html>

编辑:当节点相等时,它会进入无限循环,所以我为此添加了一个检查。