如何迭代HTML DOM并在javascript中列出所有具有深度的节点。
示例:
<div>
<img src="foo.jpg">
<p>
<span>bar</span>
</p>
</div>
会导致
答案 0 :(得分:12)
编写跟踪深度的递归函数:
function element_list(el,depth) {
console.log(el+' '+depth);
for(var i=0; i<el.children.length; i++) {
element_list(el.children[i],depth+1);
}
}
element_list(document,0);
正如CodeiSir所指出的,这也会列出文本节点,但我们可以按testing the nodeType
过滤掉它们。此代码的变体将允许/忽略其他节点类型。
function element_list(el,depth) {
if (el.nodeType === 3) return;
答案 1 :(得分:5)
请注意,其他答案是/无法正确纠正......
这也将过滤掉“TEXT”节点,而不输出BODY标签。
for ( LinkedList<Integer> bucket : bucketsOut ) {
if (bucket.peekFirst() != null) {
input[i] = bucket.pollFirst().intValue();
break;
}
}
function getDef(element, def) {
var str = ""
var childs = element.childNodes
for (var i = 0; i < childs.length; ++i) {
if (childs[i].nodeType != 3) {
str += childs[i].nodeName + " " + def + "<br />"
str += getDef(childs[i], def + 1)
}
}
return str
}
// Example
document.body.innerHTML = getDef(document.body, 0)
答案 2 :(得分:2)
是的,你可以!您必须迭代并使用一些逻辑来创建此树,但是对于您的示例,您可以执行以下操作:
var tracker = {};
Array.from(document.querySelectorAll("*")).forEach(node => {
if (!tracker[node.tagName]) tracker[node.tagName] = 1;
else tracker[node.tagName]++;
});
console.log(tracker);
您可以将其修改为在childNodes的recrusive子集上运行。这只是迭代整个文档。
选中this fiddle并打开控制台,查看tracker
的输出,该输出计算并列出标记名称。要添加深度,只需抓住parentNode.length
即可。
这是一个更新的脚本,我认为深度计算是否合适;
var tracker = {};
var depth = 0;
var prevNode;
Array.from(document.querySelectorAll("*")).forEach(node => {
if (!tracker[node.tagName]) tracker[node.tagName] = 1;
else tracker[node.tagName]++;
console.log("Node depth:", node.tagName, depth);
if (node.parentNode != prevNode) depth++;
prevNode = node;
});
console.log(tracker);
答案 3 :(得分:2)
getElementDepth
返回节点的绝对深度(从html
节点开始),以获得两个节点之间的深度差异,您可以从另一个节点中减去绝对深度。
function getElementDepthRec(element,depth)
{
if(element.parentNode==null)
return depth;
else
return getElementDepthRec(element.parentNode,depth+1);
}
function getElementDepth(element)
{
return getElementDepthRec(element,0);
}
function clickEvent() {
alert(getElementDepth(document.getElementById("d1")));
}
<!DOCTYPE html>
<html>
<body>
<div>
<div id="d1">
</div>
</div>
<button onclick="clickEvent()">calculate depth</button>
</body>
</html>
答案 4 :(得分:1)
我的原始解决方案使用fsfs.conf
循环将每个元素向上移动到DOM以确定其深度:
while
&#13;
var el = document.querySelectorAll('body *'), //all element nodes, in document order
depth,
output= document.getElementById('output'),
obj;
for (var i = 0; i < el.length; i++) {
depth = 0;
obj = el[i];
while (obj.parentNode !== document.body) { //walk the DOM
depth++;
obj = obj.parentNode;
}
output.textContent+= depth + ' ' + el[i].tagName + '\n';
}
&#13;
我提出了一个新的解决方案,它将每个元素的深度存储在一个对象中。由于querySelectorAll()
以文档顺序返回元素,因此父节点始终显示在子节点之前。因此,子节点的深度可以计算为其父节点的深度加1。
这样,我们可以在没有递归的情况下确定单次传递的深度:
<div>
<img src="foo.jpg">
<p>
<span>bar</span>
</p>
</div>
<hr>
<pre id="output"></pre>
&#13;
var el = document.querySelectorAll('body *'), //all element nodes, in document order
depths= { //stores the depths of each element
[document.body]: -1 //initialize the object
},
output= document.getElementById('output');
for (var i = 0; i < el.length; i++) {
depths[el[i]] = depths[el[i].parentNode] + 1;
output.textContent+= depths[el[i]] + ' ' + el[i].tagName + '\n';
}
&#13;
答案 5 :(得分:1)
任何寻找在节点下遍历树的东西而不使用递归*但是也给你深度(相对于头节点)......以及兄弟 - 祖先坐标的任何人:
function walkDOM( headNode ){
const stack = [ headNode ];
const depthCountDowns = [ 1 ];
while (stack.length > 0) {
const node = stack.pop();
console.log( '\ndepth ' + ( depthCountDowns.length - 1 ) + ', node: ');
console.log( node );
let lastIndex = depthCountDowns.length - 1;
depthCountDowns[ lastIndex ] = depthCountDowns[ lastIndex ] - 1;
if( node.childNodes.length ){
depthCountDowns.push( node.childNodes.length );
stack.push( ... Array.from( node.childNodes ).reverse() );
}
while( depthCountDowns[ depthCountDowns.length - 1 ] === 0 ){
depthCountDowns.splice( -1 );
}
}
}
walkDOM( el );
PS我会理解我已经放入> 0
和=== 0
来尝试提高清晰度...首先可以省略,第二个可以用前导!
取代当然。
*看看here关于JS中递归成本的令人震惊的事实(无论如何,2018-02-01的当代实现!)
答案 6 :(得分:0)
您可以使用Jquery
执行此操作$('#divId').children().each(function () {
// "this" is the current element
});
,html应如下所示:
<div id="divId">
<img src="foo.jpg">
<p>
<span>bar</span>
</p>
答案 7 :(得分:0)
(() => {
const el = document.querySelectorAll('body *');
const depths = new Map();
depths.set(document.body, -1)
el.forEach((e) => {
const p = e.parentNode;
const d = depths.get(p);
depths.set(e, d + 1);
})
return depths;
})()
这是Rick Hitchcock
的答案,但使用Map而不是object
结果Map(5) {body => -1, div => 0, img => 1, p => 1, span => 2}