2017-02-04 9 views
4

Я пытаюсь заменить весь текст между тегами, и я хочу знать самый быстрый способ сделать это.Ускоренный способ замены текста во всех элементах dom?

Примером будет пытаться заменить весь текст с произвольной строки HelloWorld, так что это:

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

Становится это:

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

Мой нынешний подход был бы:

  • Сделайте поиск по глубине (DFS) на DOM
  • Для каждого элемента разбор и определение, какая часть является текстом, а какая часть является элементом.
  • Для части, заменяющей текст.

Это было бы очень медленно, особенно пытаясь сделать это для большого документа и повторить процесс много раз. Есть ли более быстрый способ?

+1

Используйте 'TreeWalker'. –

+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, которые необходимо изменить, а затем манипулировать ими с помощью этого идентификатора класса.

Кроме того,

FYI, document.getElementById() работы по ДПП и является довольно эффективным.

+0

Он не хочет делать «DOM-поиск», и он не хочет менять определенные элементы. Он хочет иметь дело с ** всеми ** текстовыми узлами. Зачем ему нужен 'document.getElementByid'? –

+0

Да, я не вижу причины добавлять id к каждому узлу. Я хочу пересечь dom, а затем изменить внутренний текст. – Darkzuh

+0

Я не говорю, что вы делаете это с помощью document.getElementById(). Я предлагал, чтобы brower использовал только DFS, поэтому вы можете продолжить работу с DFS. (именно поэтому я поставил FYI). –

1

nodeIterator довольно быстро. У него нет проблем с вложенными узлами, независимо от того, насколько глубоко они похоронены. Примечание: добавлен красный текст с 6 уровнями. Подробности комментируются в Snippet.

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