【问题标题】:Select sibling at n distance from index (JavaScript)选择距索引 n 距离处的同级(JavaScript)
【发布时间】:2021-05-12 03:38:12
【问题描述】:

我正在寻找一种方法来遍历 DOM 元素兄弟姐妹,如 .nextSibling() 允许,但在任何给定距离,而不是仅直接下一个兄弟姐妹。

例如,如果我想相对于当前节点移动 3 个兄弟姐妹,我可以执行 nextSibling(3)siblings[2] 之类的操作。

关于如何在不循环 nextSibling n 次的情况下完成此操作的任何想法?

【问题讨论】:

  • 从性能角度来看,当带有循环的内置属性更好时,为什么要这样做?请参阅我的答案以及基准和 jsfiddle。

标签: javascript html dom element


【解决方案1】:

您可以使用parent.children 数组以及Array.prototype.indexOf 函数。

function strideSiblings(element, stride){
  var parent = element.parentNode;
  var index = Array.prototype.indexOf.call(parent.children, element);
  return parent.children[index + stride];
}

var el = document.getElementById("div-3");
var stridedSibling = strideSiblings(el, -2);
var stridedSibling1 = strideSiblings(el, 1);

console.log(stridedSibling);
console.log(stridedSibling1);
<div id="parent">
<div id="div-1">Here is div-1</div>
<div id="div-2">Here is div-2</div>
<div id="div-3">Here is div-3</div>
<div id="div-4">Here is div-4</div>
<div id="div-5">Here is div-5</div>
</div>

此答案基于 KhalilRavanna 的贡献:https://stackoverflow.com/a/23528539/9298528

【讨论】:

  • 没有父节点怎么办?
  • Chrome 和 Firefox 总是添加 ,即使提供了一个空的 HTML 文件导致 成为父级。
  • 涵盖2个浏览器,IE、Edge、Safari等呢
  • 我试用了 Edge,它的工作方式相同。也许有人可以测试其他浏览器?
  • 唯一没有父元素的元素是html(即documentElement),或者可能是DocumentFragment中的元素。你可以修改你的代码来检查parent是否为空,如果是,使用nextElementSibling/previousElementSibling作为备份,或者只是保释,说strideSiblings需要父母......
【解决方案2】:

我想在循环中使用 previousSiblingnextSibling 属性而不是使用已接受的答案进行一些测试运行,我看到 no 受益于 not 使用内置节点属性和for 循环,我看到使用带有for 循环的属性而不是接受的答案,这是我的基准测试与不同数量的兄弟姐妹以及一个jsfiddle用于运行更多基准测试 - (https://jsfiddle.net/b196t7r3/),简而言之,我的回答是使用您在问题中反对的解决方案,使用以下数字运行 jsfiddle - Chrome 版本 88.0.4324.146(官方构建)(64 位)

100,000 个兄弟姐妹

   Accepted answer execution time - 21.915000048466027 milliseconds
   Using properties with for loop - 8.234999957494438 milliseconds

10,000 个兄弟姐妹

   Accepted answer execution time - 0.8149999775923789 milliseconds
   Using properties with for loop - 0.19500002963468432 milliseconds

1000 个兄弟姐妹

   Accepted answer execution time - 0.1800000318326056 milliseconds
   Using properties with for loop - 0.059999991208314896 milliseconds

编辑:在这里添加了一个代码 sn-p,这样就不需要外部网站了:

const numberOfSiblings = 100000; //Number of divs to append to parent
const startingElement = "div-3000"; //id of element we want to pass into functions
const strideNum = 2000; //Number of siblings away from the chosen starting point



function strideSiblings(element, stride){
    var parent = element.parentNode;
    var index = Array.prototype.indexOf.call(parent.children, element);
    return parent.children[index + stride];
}

function strideSiblingsWithPreviousOrNext(element, stride){
        let sib = null;
    
    if(stride > 0){
       for(let i = 0; i < stride; i++){
           sib = element.nextSibling;
           element = sib;
       }
    }else{
         stride = stride * -1;
         for(let j = 0; j < stride; j++){
            sib = element.previousSibling;
            element = sib;
       }
    }
    
    return sib;
}

let par = document.getElementById("parent"); //get the parent div

//append the number of siblings for benchmark testing
for(let v = 0; v < numberOfSiblings; v++){
    let newDiv = document.createElement("div");  
    newDiv.id = "div-" + v;
    newDiv.textContent = "Here is div-" + v;
    par.append(newDiv);
}

var el = document.getElementById(startingElement); //get the sibling to start from

var t0 = performance.now()
var stridedSibling = strideSiblings(el, strideNum);
var t1 = performance.now()
console.log("Call to strideSiblings() took " + (t1 - t0) + " milliseconds.");

var t2 = performance.now();
stridedSibling = strideSiblingsWithPreviousOrNext(el, strideNum);
var t3 = performance.now();
console.log("Call to strideSiblingsWithPreviousOrNext() took " + (t3 - t2) + " milliseconds.");
<div id="parent">
</div>

【讨论】:

  • 如果你有代码要分享,最好在 Stack Overflow 上分享,而不是只在外部网站上分享。
  • @HereticMonkey 添加了代码sn-p,感谢您的建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-20
  • 1970-01-01
  • 2013-11-28
  • 2016-10-31
  • 2013-10-18
相关资源
最近更新 更多