我的意思是它们的数组。也就是从顶层HTML到目标元素的链,包括元素本身。
例如对于元素<A>
,它将是:
[HTML, BODY, DIV, DIV, P, SPAN, A]
我的意思是它们的数组。也就是从顶层HTML到目标元素的链,包括元素本身。
例如对于元素<A>
,它将是:
[HTML, BODY, DIV, DIV, P, SPAN, A]
稍微简短一些(也更加安全,因为target
可能不存在):
var a = document.getElementById("target");
var els = [];
while (a) {
els.unshift(a);
a = a.parentNode;
}
你可以尝试类似这样的代码:
var nodes = [];
var element = document.getElementById('yourelement');
nodes.push(element);
while(element.parentNode) {
nodes.unshift(element.parentNode);
element = element.parentNode;
}
reverse()
,而是应该使用 unshift()
替代 push()
。 - J. Holmes.push()
还有一个叫做.unshift()
的兄弟! - Robin Mabenvar nodes = [element];
同时交换前两行,并在循环之前删除 push
。我认为先将所有元素 push
进数组然后再 reverse
更快。重复的 unshift
会是 O(n^2),因为每次迭代都要移动越来越多的元素。push
然后 reverse
可以利用 push 优化的数组和在原地修改的 reverse。在可合理实现的情况下,推进(Push)很可能是摊销的常数时间。reverse
是 O(n),在原地操作中非常快。 - doug65536element.parentNode
将会抛出异常。而且没有理由为了节省一行代码而推荐使用 unshift
,因为这将导致复杂性大大增加。 - ggorlen[...(function*(e){do { yield e; } while (e = e.parentNode);})($0)]
...其中$0是你的元素。
这种方法的优点是它可以作为表达式中的值使用。
要获取没有目标元素的数组:
[...(function*(e){while (e = e.parentNode) { yield e; }})($0)]
.slice(1)
,如果您想先得到最大的父级,请添加.reverse()
。 - undefined[...(function*(e){while (e = e.parentNode) { yield e; }})($0)]
(我已更新我的答案) - Yuriy Ershov您可以遍历 element.parentNode
的链,直到到达 falsey
值,在此过程中将内容附加到数组中:
const getParents = el => {
for (var parents = []; el; el = el.parentNode) {
parents.push(el);
}
return parents;
};
const el = document.querySelector("b");
console.log(getParents(el).reverse().map(e => e.nodeName));
<div><p><span><b>Foo</b></span></div>
e.nodeName
仅用于演示,也不是必要的。&& el !== document
添加到循环停止条件中。reverse()
是原地操作,因此不需要额外的分配。在循环中使用unshift
,正如其他答案建议的那样,是二次的,并且可能会在深度不常见的DOM树上损害可扩展性,而换来的优雅程度微不足道。for(var e = document.getElementById("target"),p = [];e && e !== document;e = e.parentNode)
p.push(e);
我相信,如果您经常使用此函数,这将是最具性能的方案从长远来看在大多数情况下。之所以如此,是因为它最初会检查可能遇到的祖先深度。此外,该函数不会在每次调用时创建新数组,而是会高效地重复使用同一数组,并对其进行切片,在某些浏览器中非常优化。但是,由于我不知道任何真正有效的方法来检查最大深度,因此我只能使用效率较低的查询选择器检查。
// !IMPORTANT! When moving this coding snippet over to your production code,
// do not run the following depthtest more than once, it is not very performant
var kCurSelector="*|*", curDepth=3;
while (document.body.querySelector(kCurSelector += '>*|*')) curDepth++;
curDepth = Math.pow(2, Math.ceil(Math.log2(startDepth))),
var parentsTMP = new Array(curDepth);
function getAllParentNodes(Ele){
var curPos = curDepth;
if (Ele instanceof Node)
while (Ele !== document){
if (curPos === 0){
curPos += curDepth;
parentsTMP.length <<= 1;
parentsTMP.copyWithin(curDepth, 0, curDepth);
curDepth <<= 1;
}
parentsTMP[--curPos] = Ele;
Ele = Ele.parentNode;
}
return retArray.slice(curPos)
}
上述函数的浏览器兼容性是它可以在Edge中工作,但不能在IE中工作。如果您需要IE支持,则需要一个Array.prototype.copyWithin
填充程序。
在 JavaScript 数组中获取子节点的所有父节点
let selectedTxtElement = document.getElementById("target");
let els = [];
while (selectedTxtElement) {
els.unshift(selectedTxtElement);
selectedTxtElement = selectedTxtElement.parentNode;
}
HTML
元素处,则将语句 'a = a.parentNode' 改为a = a.parentElement
。 - Jack Gconst parents = node => (node.parentElement ? parents(node.parentElement) : []).concat([node]);
- Nate Abelepush
+reverse
仍然快了400%。哇。 - Regular Jounshift
。它的时间复杂度是二次方的。 - ggorlen