оптимизация скорости страницы: запись в DOM с использованием JavaScript и HTML - PullRequest
2 голосов
/ 23 марта 2011

У меня вопрос по скорости страницы и оптимизации кода. У меня есть страница, которая почти на 100% заполнена AJAX-звонками. У меня вопрос: быстрее ли мне кодировать несколько пустых элементов div, интервалов и т. Д. В HTML-код страницы, а затем заполнять эти элементы с помощью JavaScript? Или быстрее создать эти элементы в javascript, вставить и добавить их? Я не уверен, если есть большая разница либо. Таким образом, любая помощь / совет в этой области будет принята с благодарностью.

Ответы [ 4 ]

6 голосов
/ 23 марта 2011

Пару лет назад я провел эксперимент на этом. Намного быстрее присвоить свойству innerHTML элемента для создания сложной структуры, чем использовать повторные вызовы createElement appendChild insertBefore и т. Д. Я выкопал пост, который я сделал об этом (в список рассылки Prototype & script.aculo.us); ниже.

Помните, что анализ HTML и его рендеринг быстро - это , что делают браузеры , и они высоко оптимизированы для этого. Если вы присваиваете строку со сложной структурой HTML в свойстве innerHTML элемента контейнера, вы совершаете одно отключение от уровня JavaScript до уровня рендеринга браузера, после чего браузер выполняет синтаксический анализ и рендеринг Код может продолжаться непрерывно.

Напротив, если вы создаете какую-то сложную структуру с использованием DOM API, не только происходит много межуровневых путешествий (JavaScript -> браузер -> JavaScript), но и браузер также должен работать с DOM API, а не его внутренними структурами.

Следовательно, обычно стоит обратить внимание на хорошо написанный движок шаблонов JavaScript (если вы хотите сделать это на стороне клиента). Обычно они «компилируют» шаблон один раз в легко обрабатываемую форму, и во время обработки для определенного набора данных они используют приемы, такие как построение строки в виде фрагментов в массиве с помощью Array#push, а затем получение окончательного результата. через Array#join, передавая "" в качестве разделителя. Для больших строк это может быть быстрее, чем конкатенация строк, хотя зависит ли это (и в какой степени) от очень от реализации (Firefox SpiderMonkey против Chrome V8 против IE JScript), в отличие от innerHTML по сравнению с DOM, который меняется только на намного быстрее.

Вот список рассылки сообщение от пары лет назад, о котором я говорил (в основном то, что я говорю выше; вау, это было два года назад), * ​​1030 * вот Пасти это означает, что вот что скопировано в JSBin , и наконец ... вот код: (Обратите внимание, что код не предназначен для красоты и радость навсегда, это был быстрый взлом ... Тем не менее, да, я хотел бы думать, что взломаю что-нибудь немного лучше сейчас, два года спустя.)

Возможно, стоит преобразовать это во что-то, что будет работать на jsPerf . Боюсь, сейчас не время для этого.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<style>
#log {
    border-bottom:  1px solid black;
}
#log p {
    margin:     0;
    padding:    0;
}
</style>
<script type='text/javascript' src='//ajax.googleapis.com/ajax/libs/prototype/1/prototype.js'></script>
<script type='text/javascript'>
document.observe('dom:loaded', function() {
    $('btnDOMDirect').observe('click', useDOMDirect);
    $('btnPrototypeDOM').observe('click', usePrototypeDOM);
    $('btnHTML').observe('click', useHTML);

});

var numRows = 10;
var numCols = 10;

function usePrototypeDOM(evt)
{
    var table;
    var tbody;
    var tr;
    var td;
    var row;
    var col;
    var start;
    var end;

    start = (new Date()).getTime();

    table = new Element('table');
    tbody = new Element('tbody');
    table.appendChild(tbody);
    for (row = 0; row < numRows; ++row) {
        tr = new Element('tr');
        tbody.appendChild(tr);
        for (col = 0; col < numCols; ++col) {
            td = new Element('td');
            td.update('Row ' + row + ', col ' + col);
            tr.appendChild(td);
        }
    }
    $('targetTable').update(table);

    end = (new Date()).getTime();
    log('DOM took ' + (end - start) + 'ms');
}

function useDOMDirect(evt)
{
    var table;
    var tbody;
    var tr;
    var td;
    var row;
    var col;
    var start;
    var end;

    if (Prototype.Browser.IE) {
        alert("DOM direct doesn't work on IE because I used table elements.  Sorry.  The other two work.");
        return;
    }

    start = (new Date()).getTime();

    table = document.createElement('table');
    tbody = document.createElement('tbody');
    table.appendChild(tbody);
    for (row = 0; row < numRows; ++row) {
        tr = document.createElement('tr');
        tbody.appendChild(tr);
        for (col = 0; col < numCols; ++col) {
            td = document.createElement('td');
            td.update('Row ' + row + ', col ' + col);
            tr.appendChild(td);
        }
    }
    $('targetTable').update(table);

    end = (new Date()).getTime();
    log('DOM took ' + (end - start) + 'ms');
}

function useHTML(evt)
{
    var html;
    var row;
    var col;
    var start;
    var end;

    start = (new Date()).getTime();

    html = '<table><tbody>';
    for (row = 0; row < numRows; ++row) {
        html += '<tr>';
        for (col = 0; col < numCols; ++col) {
            html += '<td>Row ' + row + ', col ' + col + '</td>';
        }
        html += '</tr>';
    }
    html += '</tbody></table>';
    $('targetTable').update(html);

    end = (new Date()).getTime();
    log('HTML took ' + (end - start) + 'ms');
}

function log(msg)
{
    var l;
    var p;

    l = $('log');
    if (l) {
        p = new Element('p');
        p.update(msg);
        l.appendChild(p);
    }
}
</script>
</head>
<body>
<input type='button' id='btnDOMDirect' value='DOM Direct' />
<input type='button' id='btnPrototypeDOM' value='Prototype DOM' />
<input type='button' id='btnHTML' value='HTML' />
<div id='log'></div>
<div id='targetTable'></div>
</body>
</html>
0 голосов
/ 23 марта 2011

Изменить innerHTML вместо использования методов DOM.

В соответствии с этим тестом W3C DOM против innerHTML на Quirksmode, похоже, что все протестированные браузеры сильно быстрее в HTML, чем DOM.

0 голосов
/ 23 марта 2011

Если вы создаете много элементов, innerHTML может работать намного быстрее, однако это не является частью официального стандарта DOM (хотя он широко поддерживается).Я бы рекомендовал обслуживать страницу с каркасным макетом, включающим столько HTML, сколько вы можете на самой странице, а затем захватывать ссылки на соответствующие части страницы и вставлять значения стандартными методами DOM.

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

0 голосов
/ 23 марта 2011

Это всегда будет медленнее при использовании javascript, потому что он выполняется поверх загрузки страницы, а не вместе с ней, как при добавлении элементов в HTML.Тем не менее, вы могли бы также сказать, что фактическая загрузка страницы меньше (хотя и незначительно) без наличия элементов в HTML.

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

Плюс, если вы заинтересованы в поддержке семантического веб-сайта, нужны ли вам теги?Это изящно деградирует без JavaScript?И т.д. и т. Д. Это зависит от угла, который вы хотите взять, я полагаю.

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