Какой самый быстрый, безопасный и правильный метод для обхода всего DOM в чистом JS? - PullRequest
0 голосов
/ 04 января 2012

Под безопасностью я подразумеваю тот факт, что NodeList, созданный document.getElementsById('*');, является живым объектом. Некоторые элементы добавляются или удаляются динамически, когда движок JS проходит через него.

Я собираюсь сделать цикл по всему DOM (это будет в скрипте greasemonkey, поэтому не для обычного веб-использования, но я думаю, что это также применимо и там), проверить, соответствует ли CSS узла некоторым правилам и в соответствии с чтобы изменить CSS.

Этот процесс занимает некоторое время, и поскольку на веб-сайте выполняется несколько сценариев (изменение изображений / новостей и т. Д.), На которых постоянно добавляются и удаляются узлы DOM, рано или поздно будет случай, когда узел исчезнет именно тогда, когда обрабатывается.

И быстро я имею в виду, лучше ли делать это рекурсивно:

function traverseDOM(node,f) {
  if (node.nodeType !== 1) return;
  f.apply(node);
  for (var i = 0; i < node.childNodes.length; i++) {
    traverseDOM(node.childNodes[i],f);
  }
}

(но это будет тратить время на проверку nodeType) или for цикл:

nodes = document.getElementsByTagName('*');
for (var i=0; i<nodes.length; i++) {
  //do my stuff
}

(но это может привести к проблемам в конце, когда он столкнется с колеблющимся наконечником NodeList)

Ответы [ 3 ]

1 голос
/ 04 января 2012

Вот пример, не стесняйтесь попробовать.Протестировал его примерно на 170 узлах, и он не был слишком медленным, но и не обязательно быстрым:

<code>function walk (node, func) {
    func(node);
    node = node.childNodes[0];

    while (node) {
        walk(node, func);
        node = node.nextSibling;
    }
}

var doc = document; //save a reference to the document (might be a tiny bit faster... not sure)
var bd = doc.body; //start to walk the DOM from the body
var o = doc.getElementById('some_div'); //some div to output to
var arr = []; //array to collect all nodes

walk(bd, function(n){
    if (n.nodeType === 1) {
        n.style.border = "2px solid red"; //change the border color for each node that was found
        o.innerHTML += "<pre>" + n.nodeName + "
"; // выводим имя каждого узла в div arr.push (n); // addкаждый узел в массиве}}); console.log (arr.length); // записать общее количество затронутых узлов
0 голосов
/ 04 января 2012

Существует спецификация обхода элемента w3c, см. Пример на http://www.w3.org/TR/ElementTraversal/#example-3.2

0 голосов
/ 04 января 2012

JavaScript является однопоточным. Только одна функция может выполняться одновременно. Пока вы перебираете DOM, его нельзя изменить.

...