如何使用javascript创建html dom的叶节点数组

时间:2014-03-09 23:00:09

标签: javascript arrays dom recursion tree

所以我的问题基本上是这样的,如何使用javascript函数返回html文档的所有叶节点的数组。我需要稍后在该列表上执行操作。例如,如果我有html:

<body>
   <div>
      <div>
         <p id="para1"></p>
      </div>
   </div>
   <p id="para2"></p>
</body>

然后该函数应该返回一个包含id为para1和para2的两个节点的数组。

注意:我希望节点本身不是他们的id。虽然给定id我可以提取节点所以它不是一个大问题。

4 个答案:

答案 0 :(得分:1)

这是一个简单的函数来获取leafNodes所在的节点,包括文本节点(这意味着它不会返回包含文本节点的元素):

function getLeafNodes(master) {
    var nodes = Array.prototype.slice.call(master.getElementsByTagName("*"), 0);
    var leafNodes = nodes.filter(function(elem) {
        return !elem.hasChildNodes();
    });
    return leafNodes;
}

工作演示:http://jsfiddle.net/jfriend00/e9D5n/

仅供参考,.filter()方法需要IE9。如果要在早期版本的IE中使用此方法,可以为.filter()安装polyfill,或者更改为数组的手动迭代。


而且,如果您不想考虑文本节点,这是一个版本,所以您正在寻找叶元素,即使它们中有文本节点:

function getLeafNodes(master) {
    var nodes = Array.prototype.slice.call(master.getElementsByTagName("*"), 0);
    var leafNodes = nodes.filter(function(elem) {
        if (elem.hasChildNodes()) {
            // see if any of the child nodes are elements
            for (var i = 0; i < elem.childNodes.length; i++) {
                if (elem.childNodes[i].nodeType == 1) {
                    // there is a child element, so return false to not include
                    // this parent element
                    return false;
                }
            }
        }
        return true;
    });
    return leafNodes;
}

工作演示:http://jsfiddle.net/jfriend00/xu7rv/


而且,这是一个忽略文本节点的递归解决方案:

function getLeafNodes(master) {
    var results = [];
    var children = master.childNodes;
    for (var i = 0; i < children.length; i++) {
        if (children[i].nodeType == 1) {
            var childLeafs = getLeafNodes(children[i]);
            if (childLeafs.length) {
                // if we had child leafs, then concat them onto our current results
                results = results.concat(childLeafs);
            } else {
                // if we didn't have child leafs, then this must be a leaf
                results.push(children[i]);
            }
        }
    }
    // if we didn't find any leaves at this level, then this must be a leaf
    if (!results.length) {
        results.push(master);
    }
    return results;
}

工作演示:http://jsfiddle.net/jfriend00/jNn8H/

答案 1 :(得分:0)

我假设“叶子节点”,你的意思是一个没有孩子的元素。在这种情况下,您可以获取所有元素,然后遍历每个元素,检查它是否有任何子元素,如果没有将它添加到数组中:

var leaves = new Array();
var els = document.body.getElementsByTagName("*");
for (var i = 0; i < els.length; i++) {
    if (els[i].children.length === 0) {
        leaves.push(els[i]);
    }
}

答案 2 :(得分:-1)

也许以下内容可行?

var paraEl=new Array();
for(i=0;i<document.getElementsByTagName("p").length;i++){
    paraEl[i]=document.getElementsByTagName("p")[i];
}

但是你知道,document.getElementsByTagName(“p”)已经是一个数组了,对吗?

答案 3 :(得分:-1)

因此,您似乎想知道如何将节点添加到数组并返回数组。只需始终从函数返回一个数组并合并它们:

function getLeaves(element) {
    if (element.children.length === 0) {
        return [element];
    }
    var leaves = [];
    for (var i = 0, l = element.children.length; i < l; i++) {
        leaves.push.apply(leaves, getLeaves(element.children[i]));
    }
    return leaves;
}

DEMO

或者,您可以向下传递数组,当元素为假时,它只是将其自身添加到其中:

function getLeaves(element, arr) {
    // create an array if none is passed. This happens in the first call.
    arr = arr || [];
    if (element.children.length === 0) {
        arr.push(element);
    }
    var leaves = [];
    for (var i = 0, l = element.children.length; i < l; i++) {
        getLeaves(element.children[i], arr);
    }
    return arr;
}

DEMO