Подтвердить что ты не робот

Лучшая практика использования DOM Level 0 в современных приложениях JavaScript

Существует ли согласованный набор "лучших практик" для использования коллекций DOM Level 0 в современных приложениях JavaScript? (document.forms, document.images и т.д.)

В приложениях, использующих jQuery, я заметил тенденцию, скажем, изменить содержимое раскрывающегося списка с помощью $(...).html(), чтобы отключить базовые узлы, вместо использования element.options[]. Это потому, что лучше избегать коллекций DOM 0 или потому, что jQuery упрощает изменение базовой структуры DOM?

Изменить: Я думаю, что часть вопроса включает в себя, являются ли старые функции надежными кросс-браузерами. Я помню, что когда-то IE автоматически добавлял теги <tbody> к вашей таблице, а firefox - нет. Это заставило ходить по дереву болезненного кросс-браузера. Аналогично, element.options[] имел проблемы при изменении параметров в коллекции. Являются ли эти ребята надежными кросс-браузер?

4b9b3361

Ответ 1

Прежде всего, большой вопрос.

Функциональность DOM Level 0-1 - это мой любимый инструментарий для работы. Поддержка огромна. Я расскажу о плюсах и минусах для каждого подмножества DOM Level 0 ниже:

События уровня DOM

Так как они добавлены как свойства ElementNode, вы можете иметь только один обработчик. В некоторых случаях (например, делегирование событий) это обременительно. Тем не менее, я чувствую, что DOM достаточно разнообразен (особенно по мере увеличения вашего проекта), чтобы иметь достаточно места для обработчиков уровня DOM 0. Слушателям DOM Level 2 очень сложно реализовать без библиотеки/рамки, чтобы сгладить более старые браузеры. Даже разработчик Flash (слушатели используются повсюду), события DOM 0 мне намного легче. Одним из основных моментов является тот факт, что значение this установлено для вас (без взлома IE и кашля, как и у другой модели). Например, рассмотрите эту разметку:

<div id="foo">Cick Me!</div>

Теперь все, что нужно сделать, это выбор и привязка обработчика DOM Level 0.

var foo = document.getElementById("foo");
function bar()
{
    console.log(this); //<div id="foo">
}
foo.onclick = bar;

Это очень простой способ выбора элементов и альтернативы Event.currentTarget;

Здесь обсуждаются события DOM Level 0 и DOM Level 2: [ссылка]


DOM Уровень 0 HTMLCollections

Bar none, HTMLCollections - моя любимая функция DOM. Поскольку узлы выбраны для вас, нет необходимости запускать запросы. На мой взгляд, сегодня они являются наиболее упущенной функцией DOM. Обход названия, такой как: collection["name"], очень удобен и, безусловно, помогает при перемещении форм. Например, рассмотрим этот бит разметки:

<form action="./" id="foo" name="foo" method="post" onsubmit="return false;">
    <fieldset>
        <legend>Dummy Form</legend>
        <input type="text" name="bar">
        <select name="baz">
            <option selected value="1">1</option>
        </select>
    </fieldset>
</form>

Есть много способов DOM Level 0 для решения этой проблемы.

Конечно, метод 3 является более предпочтительным. Это DOM Level 1, а не DOM Level 0. Однако обход названия подходит для HTMLFormElement.elements HTMLCollection. Поскольку вы должны использовать атрибуты name для элементов формы, вы можете легко получить к ним доступ без атрибута id.

Пример: var baz = foo.elements.baz;

При использовании переключателей, которые имеют одно и то же имя (для того, чтобы сделать только один выбор за раз), вы можете использовать HTMLFormElement.elements HTMLCollection для выбора всех переключателей. Это очень мощно. Рассмотрим эту разметку:

<form action="./" id="foo" name="foo" method="post" onsubmit="return false;">
    <fieldset>
        <legend>Radio Buttons</legend>
        <label for="select_1">1</label>
        <input id="select_1" type="radio" name="selectable" value="a">
        <label for="select_2">2</label>
        <input id="select_2" type="radio" name="selectable" value="b">
        <label for="select_3">3</label>
        <input id="select_3" type="radio" name="selectable" value="c">
    </fieldset>
</form>

Вы можете использовать этот простой код и каждый переключатель со значением атрибута name "selectable":

  • var foo = document.forms.foo;
    var selectables = foo.elements.selectable;
    console.log(selectables); //[input#select_1 a, input#select_2 b, input#select_3 c]
    

    Демо: http://jsbin.com/upiyom/edit#preview

  • var foo = document.forms.foo;
    var selectables = foo.selectable;
    console.log(selectables); //[input#select_1 a, input#select_2 b, input#select_3 c]
    

    Демо: http://jsbin.com/upiyom/2/edit#preview

Вариант 2 позволяет полностью обойти elements HTMLCollection. Хотя это не так ясно, как вариант 1, он все еще используется сегодня.

HTMLCollections стали более густонаселенными и намного более разнообразными с момента введения DOM Level 0. Например, взгляните на HTMLCollections, доступные для таблицы. Это ошеломляет. Там HTMLTableElement.rows, HTMLTableElement.tBodies, HTMLTableSectionElement (thead, tbody, tfoot).rows > и HTMLTableRowElement.cells. Эти коллекции очень мощные и сделали DOM обход намного проще с таблицами (позволяя вам их использовать).


Свойства уровня DOM уровня

Пока свойства на элементах ElementNodes были не такими разнообразными в DOM Level 0, как сейчас, есть еще несколько драгоценных камней, которые нужно отметить:

HTMLInputElement.defaultChecked

defaultChecked позволяет обойти поиск через HTMLInputElement checked атрибут полностью, потому что он сохраняет логическое значение на основе этого значения атрибута. Это означает, что вам не нужно клонировать через неряшливые решения для сборки IE, связанные с get/set/removeAttribute. Позже свойство defaultValue также будет добавлено для заполнения аналогичной потребности.

document.lastModified [нестандартный]

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

HTMLDocument.title

title задержит заголовок документа для вас. Его использование в лучшем случае - небольшая ниша.


В отношении вашего вопроса tbody браузеры сегодня добавляют HTMLTableSectionElement (tbody), если вы не продвинете надлежащую структуру DOM. Вы должны знать правильную разметку таблиц, поэтому это не будет проблемой в будущем:).

Пример разметки:

Неверно:

<table>
    <!-- tbody will be inserted here and will wrap the tr -->
    <tr>
        <td>Hello, World!</tr>
    </tr>
</table>

Справа:

<table>
    <tbody>
        <tr>
            <td>Hello, World!</td>
        </tr>
    </tbody>
</table>

Демо: http://jsbin.com/exomub/edit#preview


Резюме

Основная проблема, которая должна быть вызвана домой, заключается в том, что большая часть DOM Level 0 стандартизирована на уровнях DOM 1 и 2. Это означает, что поддержка браузера обширна (поскольку она действительно старая). Не должно быть слишком много опасений использовать его - помимо некоторых случаев кросс-кода в старых сборках браузера. В конце концов, это ваш выбор.

Я хотел бы добавить, что я только очень кратко - в прошлом - работал с HTML/JavaScript. Я делаю это как хобби, поэтому я не причастен к "страшным историям" о том, что браузеры/проекты пошли не так.

Надеюсь, это прояснило некоторые вещи.

Матф

ElementNode - Node с nodeType == 1

HTMLCollection. Живой массив NodeList, собранный браузером

Ответ 2

Это очень интересный вопрос. Вот мои два цента.

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

Теперь нет очевидного технического недостатка, который мешает вам использовать Level 0, если вы этого хотите. Например, я был бы удивлен, если итерация над element.options была медленнее, чем над element.getElementsByTagName("option") или $("option", element). Первый синтаксис также может быть более читабельным, чем альтернативы.

Поддержка браузера также не является проблемой. Уровень 0 старше, чем грязь, и поддерживается более десяти лет каждым браузером script -aware под солнцем.

Однако вышеизложенное касается выбора, а не эффективности, с чем связана вторая половина вашего вопроса. Действительно, вы можете выполнять итерацию более element.options или $("option", element) или $(element).children("option") с большей или меньшей степенью эффективности, но если вам приходится выполнять тяжелую работу (например, уничтожить существующие элементы <option> и добавить новые), то использование element.innerHTML или $(element).html(), безусловно, будет быстрее.

Это потому, что свойство innerHTML Level 0 и html ( ) Метод jQuery (который использует innerHTML внутренне) делегирует все разметки разбора и манипуляции с DOM в браузер, который обычно написан на языке более низкого уровня и сильно оптимизирован для этих задач. Удаление элементов <option> один за другим в цикле Javascript всегда будет медленнее в сравнении, и в этой ситуации использование DOM Level 0 или всех колоколов и свистов jQuery не имеет абсолютно никакого значения.

Ответ 3

Начну с того, что я не знаю никаких "официальных" заявлений, таких как "DOM Level 0 считается вредным". Это только мое мнение.

Я думаю, это зависит от случая.

Проблема заключается в том, что проблематично, особенно с динамически сгенерированными/модифицированными документами, нацеливать определенные элементы с помощью таких коллекций, как documents.forms или documents.images. Каждый раз, когда я вижу, что кто-то пишет document.forms[0], я съеживаюсь.

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

Исключения, которые у меня есть, - это когда вы работаете в среде, отличной от jQuery, и получаете доступ к таким вещам, как selectElement.options или tbodyElement.rows. В таких случаях это действительно проще, когда вы делаете основные вещи, такие как добавление или удаление элементов.

Ответ 4

В приложениях, использующих jQuery, я заметил тенденцию, скажем, изменить содержимое раскрывающегося списка с помощью $(...). html(), чтобы отключить базовые узлы, а не использовать элемент. опции[]. Это потому, что лучше избегать коллекций dom0 или потому что jQuery значительно упрощает изменение базовой структуры DOM?

Это можно объяснить довольно легко. 95% разработчиков jQuery не знают, существует ли DOM API или могут быть использованы.

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

Лично я бы сказал, что использую DOM 0, но опять же, лично я бы сказал, использую DOM-прокладку и не использую jQuery. Все это вопрос выбора.

Сделайте то, что является наиболее поддерживаемым

Ответ 5

К лучшему или к худшему я использую чистые функции уровня DOM 0 в основном для отладки. Иногда быстрее проверять document.forms [0].элементы для входов.

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

Я действительно считаю, что вам лучше знать весь этот нулевой арсенал DOM, но это даже лучше, если вы знаете обо всех этих современных чистых DOM-не-know-which-level-it-is-exaclty уровнях API. Например, коллекции ClassList хороши. Я имею в виду, если вы используете фреймворк, вы всегда должны знать, почему вам нужно точно.