替换所有 dom 元素中文本的更快方法?

Faster way of replacing text in all dom elements?

我正在尝试替换标签之间的所有文本,我想知道这样做的最快方法。

一个例子是尝试用任意字符串 helloWorld 替换所有文本,这样:

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

变成这样:

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

我目前的做法是:

这对我来说真的很慢,尤其是尝试对大型文档执行此操作并且必须多次重复该过程。有没有更快的方法?

DOM 浏览器搜索速度很快,而且还优化了。 因此,我建议在需要更改的 DOM 元素上添加一些常见的 class,然后使用该 class 标识符对其进行操作。

此外,

仅供参考,document.getElementById() 适用于 DFS,效率很高。

nodeIterator 相当快。无论嵌套节点埋得多深,它都没有问题。注意:添加了向下 6 级的红色文本。摘要中评论了详细信息。

片段

/* 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>

使用TreeWalker object as the most fast tool for DOM traversal.
A TreeWalker can be created using the 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

遍历你的 HTML 而不是像这样找到 nodeValue:

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

https://jsfiddle.net/q7ewbswx/

不需要解析每个元素来查找文本节点,你可以递归遍历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>