2017-02-04 90 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/