getElementsByTagName()等效于textNodes

时间:2010-04-05 16:58:37

标签: javascript dom dhtml textnode

有没有办法获取文档中所有textNode个对象的集合?

getElementsByTagName()适用于Elements,但textNode不是元素。

更新:我意识到这可以通过走DOM来实现 - 正如以下许多建议的那样。我知道如何编写一个DOM-walker函数来查看文档中的每个节点。我希望有一些浏览器原生的方式来做到这一点。毕竟有点奇怪的是,我可以通过一个内置调用获得所有<input>,但不是所有textNode

7 个答案:

答案 0 :(得分:101)

<强>更新

我已经概述了超过1000次运行的这6种方法中的每种方法的一些基本性能测试。 getElementsByTagName是最快的,但它做了一半的工作,因为它没有选择所有元素,只有一种特定类型的标记(我认为p),并盲目地假设它的firstChild是一个文本元件。它可能没有什么缺陷,但它的用于演示目的并将其性能与TreeWalker进行比较。 Run the tests yourselves on jsfiddle查看结果。

  1. 使用TreeWalker
  2. 自定义迭代遍历
  3. 自定义递归遍历
  4. Xpath查询
  5. querySelectorAll
  6. 的getElementsByTagName
  7. 让我们暂时假设有一种方法允许您本地获取所有Text个节点。您仍然必须遍历每个生成的文本节点并调用node.nodeValue以获取实际文本,就像使用任何DOM节点一样。因此,性能问题不是迭代文本节点,而是遍历所有非文本节点并检查其类型。我会争辩(基于结果)TreeWalker的表现速度与getElementsByTagName一样快,如果不是更快(即使getElementsByTagName玩有障碍)。

    Ran each test 1000 times.
    
    Method                  Total ms        Average ms
    --------------------------------------------------
    document.TreeWalker          301            0.301
    Iterative Traverser          769            0.769
    Recursive Traverser         7352            7.352
    XPath query                 1849            1.849
    querySelectorAll            1725            1.725
    getElementsByTagName         212            0.212
    

    每种方法的来源:

    <强> TreeWalker

    function nativeTreeWalker() {
        var walker = document.createTreeWalker(
            document.body, 
            NodeFilter.SHOW_TEXT, 
            null, 
            false
        );
    
        var node;
        var textNodes = [];
    
        while(node = walker.nextNode()) {
            textNodes.push(node.nodeValue);
        }
    }
    

    递归树遍历

    function customRecursiveTreeWalker() {
        var result = [];
    
        (function findTextNodes(current) {
            for(var i = 0; i < current.childNodes.length; i++) {
                var child = current.childNodes[i];
                if(child.nodeType == 3) {
                    result.push(child.nodeValue);
                }
                else {
                    findTextNodes(child);
                }
            }
        })(document.body);
    }
    

    迭代树遍历

    function customIterativeTreeWalker() {
        var result = [];
        var root = document.body;
    
        var node = root.childNodes[0];
        while(node != null) {
            if(node.nodeType == 3) { /* Fixed a bug here. Thanks @theazureshadow */
                result.push(node.nodeValue);
            }
    
            if(node.hasChildNodes()) {
                node = node.firstChild;
            }
            else {
                while(node.nextSibling == null && node != root) {
                    node = node.parentNode;
                }
                node = node.nextSibling;
            }
        }
    }
    

    <强> querySelectorAll

    function nativeSelector() {
        var elements = document.querySelectorAll("body, body *"); /* Fixed a bug here. Thanks @theazureshadow */
        var results = [];
        var child;
        for(var i = 0; i < elements.length; i++) {
            child = elements[i].childNodes[0];
            if(elements[i].hasChildNodes() && child.nodeType == 3) {
                results.push(child.nodeValue);
            }
        }
    }
    

    getElementsByTagName (差点)

    function getElementsByTagName() {
        var elements = document.getElementsByTagName("p");
        var results = [];
        for(var i = 0; i < elements.length; i++) {
            results.push(elements[i].childNodes[0].nodeValue);
        }
    }
    

    <强>的XPath

    function xpathSelector() {
        var xpathResult = document.evaluate(
            "//*/text()", 
            document, 
            null, 
            XPathResult.ORDERED_NODE_ITERATOR_TYPE, 
            null
        );
    
        var results = [], res;
        while(res = xpathResult.iterateNext()) {
            results.push(res.nodeValue);  /* Fixed a bug here. Thanks @theazureshadow */
        }
    }
    

    此外,您可能会发现此讨论很有用 - http://bytes.com/topic/javascript/answers/153239-how-do-i-get-elements-text-node

答案 1 :(得分:4)

我知道你特意要求收藏,但是如果你只是非正式地意味着并且不关心它们是否都被组合成一个大字符串,你可以使用:

var allTextAsString = document.documentElement.textContent || document.documentElement.innerText;

......第一项是DOM3标准方法。但请注意innerText似乎排除了支持它的实现中的脚本或样式标记内容(至少是IE和Chrome),而textContent包含它们(在Firefox和Chrome中)。

答案 2 :(得分:2)

这是最快的TreeWalker方法的现代function getTextNodesIterator(el) { // Returns an iterable TreeWalker const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT); const next = () => { const value = walker.nextNode(); return { value, done: !value }; }; walker[Symbol.iterator] = () => ({next}); return walker; } 版本:

for (const textNode of getTextNodesIterator(document.body)) {
    console.log(textNode)
}

用法:

function getTextNodes(el) { // Returns an array of Text nodes
    const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
    const nodes = [];
    while (walker.nextNode()) {
        nodes.push(walker.currentNode);
    }
    return nodes;
}

但如果在循环时移动节点,循环可能会卡住。

这更安全:

 echo '<img #img id="img-' . $i . '" name="' . $filename . '" class="lazy" data-original="'.$image.'" />';

答案 3 :(得分:1)

 document.deepText= function(hoo, fun){
        var A= [], tem;
        if(hoo){
            hoo= hoo.firstChild;
            while(hoo!= null){
                if(hoo.nodeType== 3){
                    if(typeof fun== 'function'){
                        tem= fun(hoo);
                        if(tem!= undefined) A[A.length]= tem;
                    }
                    else A[A.length]= hoo;
                }
                else A= A.concat(document.deepText(hoo, fun));
                hoo= hoo.nextSibling;
            }
        }
        return A;
    }

/ * 您可以返回某些父元素的所有后代文本节点的数组, 或者你可以传递一些功能并做一些事情(找到或替换或其他) 到现在的文本。

此示例返回正文中非空白文本节点的文本:

var A= document.deepText(document.body, function(t){
    var tem= t.data;
    return /\S/.test(tem)? tem: undefined;
});
alert(A.join('\n'))

* /

方便搜索和替换,突出显示等

答案 4 :(得分:1)

这是一个更惯用的(希望是)更容易理解的选择。

function getText(node) {
    // recurse into each child node
    if (node.hasChildNodes()) {
        node.childNodes.forEach(getText);
    }
    // get content of each non-empty text node
    else if (node.nodeType === Node.TEXT_NODE) {
        const text = node.textContent.trim();
        if (text) {
            console.log(text); // do something
        }
    }
}

答案 5 :(得分:0)

var el1 = document.childNodes[0]
function get(node,ob)
{
        ob = ob || {};

        if(node.childElementCount)
        {

            ob[node.nodeName] = {}
            ob[node.nodeName]["text"] = [];
            for(var x = 0; x < node.childNodes.length;x++)
            {   
                if(node.childNodes[x].nodeType == 3)
                {
                    var txt = node.childNodes[x].nodeValue;


                    ob[node.nodeName]["text"].push(txt)
                    continue
                }
                get(node.childNodes[x],ob[node.nodeName])       
            };  
        }
        else
        {
            ob[node.nodeName]   = (node.childNodes[0] == undefined ? null :node.childNodes[0].nodeValue )
        }
        return ob
}



var o = get(el1)
console.log(o)

答案 6 :(得分:0)

createTreeWalker被弃用后,您可以使用

  /**
   * Get all text nodes under an element
   * @param {!Element} el
   * @return {Array<!Node>}
   */
  function getTextNodes(el) {
    const iterator = document.createNodeIterator(el, NodeFilter.SHOW_TEXT);
    const textNodes = [];
    let currentTextNode;
    while ((currentTextNode = iterator.nextNode())) {
      textNodes.push(currentTextNode);
    }
    return textNodes;
  }