2017-02-04 62 views
4

我试图替换标签之间的所有文本,我想知道这样做的最快方式。更快取代所有DOM元素中的文字?

一个例子是试图取代与任意字符串helloWorld的所有文字,让这样的:

<div> 
    <div> 
     RandomText1 
     <div> 
      RandomText2 
     </div> 
    </div> 
</div> 

变为这样:

<div> 
    <div> 
     helloWorld 
     <div> 
      helloWorld 
     </div> 
    </div> 
</div> 

我目前的做法是:

  • DOM上的深度优先搜索(DFS)
  • 对于每个元素进行解析并确定哪部分是文本,哪部分是元素。
  • 对于文本部分进行替换。

这对我来说真的很慢,特别是要为大文档做这些事情,而且不得不多次重复这个过程。有更快的方法吗?

+1

使用'TreeWalker'。 – 2017-02-04 13:24:47

+0

或者'nodeIterator' – zer00ne

+0

你可以在Js中使用这种方法冒泡的概念 –

回答

3

你并不需要解析每一个元素查找文本节点,你可以递归遍历元素的childNodes财产

var newText = 'hello world'; 
 
function replaceTextNodes(node) { 
 
    node.childNodes.forEach(function(el) { 
 
    if (el.nodeType === 3) { // If this is a text node, replace the text 
 
     if (el.nodeValue.trim() !== "") { // Ignore this node it it an empty text node 
 
     el.nodeValue = newText; 
 
     } 
 
    } else { // Else recurse on this node 
 
     replaceTextNodes(el); 
 
    } 
 
    }); 
 
} 
 

 
var onClick = replaceTextNodes.bind(null, document.querySelector('#container')); 
 
document.querySelector('#replace').addEventListener('click', onClick);
<div id='container'> 
 
    <div> 
 
    RandomText1 
 
    <div> 
 
     RandomText2 
 
     <ul> 
 
     <li>RandomText3</li> 
 
     </ul> 
 
    </div> 
 
    </div> 
 
</div> 
 
<button id="replace">Replace</button>

+0

干杯,出色的解决方案:D – Darkzuh

0

由浏览器完成的DOM搜索速度非常快,并且它也进行了优化。 因此,我建议在需要修改的DOM元素上添加一些常用的类,然后使用该类标识符来处理它们。

此外,

仅供参考,document.getElementById()作品的DFS,是非常有效的。

+0

他不想执行“DOM搜索”,但他不想更改某些元素。他想处理所有**文本节点。为什么他需要'document.getElementByid'? – 2017-02-04 13:25:46

+0

是的,我没有看到将id添加到每个节点的原因。我想遍历DOM,然后更改内部文本 – Darkzuh

+0

我不是说你用document.getElementById()来完成它。 我给出的建议是,浏览器仅使用DFS,因此您可以继续使用DFS。 (这就是为什么我把FYI)。 –

1

nodeIterator非常快。无论嵌套节点多深埋藏,它都没有问题。注意:添加了6个级别的红色文本。详细信息在Snippet中进行了评论。

代码片段

/* Create a custom filter which will... 
 
||...the 3rd parameter of createNodeIterator method... 
 
*/ 
 

 
function textFilter(node) { 
 
    // if .nodeType is 3 (3 is text, 1 is element) 
 
    if (node.nodeType === 3) { 
 
    // Set .nodeValue to 'hellowWorld' 
 
    node.nodeValue = 'helloWorld'; 
 
    // Return NodeFilter object to accept node 
 
    return NodeFilter.FILTER_ACCEPT; 
 
    } 
 
    // Otherwise ignore node 
 
    return NodeFilter.FILTER_SKIP; 
 
} 
 

 
function findText() { 
 
    // Reference the rootNode 
 
    var content = document.querySelector('body'); 
 

 
    /* Create nodeIterator passing 
 
    || content or rootNode 
 
    || NodeFilter object or WhatToShow property 
 
    || Custom filter function 
 
    */ 
 
    var iterator = document.createNodeIterator(content, NodeFilter.SHOW_TEXT, textFilter); 
 
    // Advance to the next sibling or descend to node's children nodes 
 
    var node = iterator.nextNode(); 
 
    // While there is a node... 
 
    while (node) { 
 
    // ...Go on to it...rinse, lather, and repeat 
 
    node = iterator.nextNode(); 
 
    } 
 

 
} 
 

 
findText();
.mark { 
 
    color: red; 
 
}
<div> 
 
    <div> 
 
    RandomText1 
 
    <div> 
 
     RandomText2 
 
    </div> 
 
    </div> 
 
</div> 
 
<div> 
 
    <div> 
 
    <div> 
 
     <div> 
 
     <div> 
 
      <div class='mark'> 
 
      6 Deep! 
 
      </div> 
 
     </div> 
 
     </div> 
 
    </div> 
 
    </div> 
 
    <div> 
 
    RandomText1 
 
    <div> 
 
     RandomText2 
 
    </div> 
 
    </div> 
 
</div> 
 
<div> 
 
    <div> 
 
    RandomText1 
 
    <div> 
 
     RandomText2 
 
    </div> 
 
    </div> 
 
</div> 
 
<div> 
 
    <div> 
 
    RandomText1 
 
    <div> 
 
     RandomText2 
 
    </div> 
 
    </div> 
 
</div> 
 
<div> 
 
    <div> 
 
    RandomText1 
 
    <div> 
 
     RandomText2 
 
    </div> 
 
    </div> 
 
</div>

+0

非常感谢:D – Darkzuh

+0

非常欢迎:) – zer00ne

1

使用TreeWalker对象为DOM遍历最快速的工具。
A TreeWalker可以使用Document.createTreeWalker()方法创建。

function replaceAllText(newText) { 
 
    var walker = document.createTreeWalker(
 
     document.body, // root node 
 
     NodeFilter.SHOW_TEXT, // filtering only text nodes 
 
     null, 
 
     false 
 
    ); 
 
    
 
    while (walker.nextNode()) { 
 
     if (walker.currentNode.nodeValue.trim()) // if it's not empty(whitespaced) node 
 
      walker.currentNode.nodeValue = newText; 
 
    } 
 
} 
 

 
replaceAllText("helloWorld");
<div> 
 
    <div> 
 
     RandomText1 
 
     <div> 
 
      RandomText2 
 
     </div> 
 
    </div> 
 
</div>

https://developer.mozilla.org/en-US/docs/Web/API/Document/createTreeWalker

Performance test demonstration

0

循环在你的HTML比找到的nodeValue是这样的:

document.querySelectorAll('div').forEach(function(o,i){ 
    console.log(o.firstChild && o.firstChild.nodeValue); 
}) 

https://jsfiddle.net/q7ewbswx/