Более эффективный способ анализа элементов dom? - PullRequest
1 голос
/ 07 июля 2011

У меня есть HTML-код, который мне нужно проанализировать.

В основном я иду через дом данного элемента.Захват текстовых узлов и узлов элементов.

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

Таким образом, когда узел элемента найден, его стиль применяется к любому обнаруженному текстовому узлупока не будет найден другой узел элемента и старый стиль не будет заменен новым.

Код ниже работает.Если у вас есть предложение или короткий абзац в элементе источника, он воспроизводит текст точно менее чем за секунду.Чем длиннее текст, тем дольше (дух).

Интересно, что чем больше текста в элементе назначения, тем больше времени занимает.Так что, если я выполнил эту функцию 10 раз на одном и том же элементе источника с тем же самым обрабатываемым текстом, она будет выполняться медленнее в 10-й раз, чем в 1-й раз, возможно потому, что сложнее отобразить текст в элементетам уже есть контент.

В любом случае, мне действительно нужно найти способ заставить эту штуку работать быстрее.

И наконец, вот пример фрагмента HTML, который может понадобиться этой вещи:

<span style='blah: blah;'> Some text </span><span>Even more text </span> <p> stuff </p>

Полученный HTML-код будет:

<span style='blah: blah;'>S</span>
<span style='blah: blah;'>o</span>
<span style='blah: blah;'>m</span>
<span style='blah: blah;'>e</span>
<span style='blah: blah;'> </span> 
<span style='blah: blah;'>t</span>
<span style='blah: blah;'>e</span>
<span style='blah: blah;'>x</span>
<span style='blah: blah;'>t</span> 
.......

Ничего особенного.

Вот код:

Код:

ed.rta_to_arr_paste = function(ele, cur_style) {

    var child_arr = ele.childNodes;

    if(!(is_set(cur_style))) {
        cur_style = {};
    }

    for(var i = 0; i < child_arr.length; i++) {
        if(child_arr[i].nodeType == 1) {
            if(cur_style != child_arr[i].style) {
                cur_style = child_arr[i].style;
            }
        } else if(child_arr[i].nodeType == 3) {

            for(var n = 0; n < child_arr[i].nodeValue.length; n++) {

                var span = ed.add_single_char(child_arr[i].nodeValue.charAt(n), cur_style);
            }
        }
        ed.rta_to_arr_paste(child_arr[i], cur_style);
    }

}

РЕДАКТИРОВАТЬ:
Один из примеров такой системы используется в документах Google.

Когда пользователь вставляет текст в документ, он сначала выводится за пределы экрана, а затем обрабатывается с помощью функции, аналогичной (я предполагаю) этой.Затем он перепечатывает текст в документе.Все происходит очень быстро (если текст не очень длинный).

Ответы [ 2 ]

5 голосов
/ 07 июля 2011

Похоже, вы непосредственно вставляете новые элементы в дерево DOM, поэтому я думаю, что вы можете добиться наилучшего улучшения, если не сделав этого .

Избегайте вставки множества элементов по одномуодним.Каждый раз, когда вы вставляете элемент, браузер должен пересчитать макет страницы, и это занимает время.

Вместо этого, добавьте узлы к элементу, отсутствующему в DOM, лучше всего будет использовать DocumentFragment, который можно создать с помощью document.createDocumentFragment.

Затем все, что вам нужно сделать, это вставить этот фрагмент, и браузер должен выполнить только один пересчет.

Обновление:

Вы также можете попробовать использовать регулярные выражения для преобразования текста в элементы span.

var html = value.replace(/(.)/g, "<span>$1</span>")

По крайней мере, в моем простом тесте (не уверен, что тестовые сценарии хороши в этом случае), он работает намного лучше, чем создание span элементов и добавление их во фрагмент документа:

Обновление 2: Я также настроил тесты так, чтобы установил сгенерированные элементы / строки в качестве содержимого элемента, и, к сожалению, это снижает скорость использования replace.Но, возможно, все же стоит проверить это:

http://jsperf.com/regex-vs-loop


Вам также следует избегать повторного доступа к свойству:

ed.rta_to_arr_paste = function(ele, cur_style) {

    var child_arr = ele.childNodes;

    if(!(is_set(cur_style))) {
        cur_style = {};
    }

    for(var i = 0, l = child_arr; i <l; i++) {
        var child = child_arr[i];
        if(child.nodeType == 1) {
            // this will always be true, because `el.style` returns an object
            // so comparing it does not make sense. Maybe just override it always
            if(cur_style != child.style) { 
                cur_style = child.style;
            }
            // doesn't need to be called for other nodes
            ed.rta_to_arr_paste(child, cur_style); 
        } 
        else if(child.nodeType == 3) {
            var value = child.nodeValue;
            for(var n = 0, ln = value.length; n < ln; n++) {
                ed.add_single_char(value.charAt(n), cur_style);
            }
        }       
    }
}
0 голосов
/ 07 июля 2011

Похоже, вы ищете DOM для элемента при каждом вызове. Я бы подумал, что вместо этого вы бы прикрепили событие к элементам DOM в чем-то вроде onload (или, что еще лучше, используйте jquery document.ready). Я бы также (в качестве незначительного рефакторинга) сначала проверил, чтобы убедиться, что у вас есть дочерние элементы (child_arr.length> 0) до вызова цикла for (это может быть совершенно незначительным, но рекомендуется)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...