Лучшая практика использования DOM Level 0 в современных приложениях JavaScript - PullRequest
23 голосов
/ 05 июля 2011

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

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

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

Ответы [ 5 ]

16 голосов
/ 09 августа 2011

Прежде всего, отличный вопрос.

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

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

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

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

Теперь все, что нужно сделать, - это выбрать и прикрепить обработчик DOM уровня 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 Level 0 HTMLCollections

Без исключений, 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>

Существует множество способов справиться с этим на уровне 0.

  1. var foo = document.forms.foo; //<form id="foo" onsubmit="return false;" method="post" name="foo" action="./">

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

  2. var foo = document.forms[0]; //<form id="foo" onsubmit="return false;" method="post" name="foo" action="./">

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

  3. var foo = document.getElementById("foo"); //<form id="foo" onsubmit="return false;" method="post" name="foo" action="./">

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

Конечно, способ 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 «выбираемый»:

  1. 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

  2. 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 Level 0 Свойства

Хотя свойства на 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.Я делаю это как хобби, поэтому я не причастен к "ужасным историям" о неудачных браузерах / проектах.

Надеюсь, это кое-что прояснило.

-Matt

ElementNode - Узел с nodeType == 1

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

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

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

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

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

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

Однако вышеизложенное касается выбора , а не эффективности , и это то, чем занимается вторая половина вашего вопроса. Действительно, вы можете перебирать 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 голосов
/ 06 июля 2011

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

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

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

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

Делай, что больше всего в обслуживании

3 голосов
/ 05 июля 2011

Я начну с того, что не знаю ни одного «официального» заявления, например, «DOM Level 0 считается вредным». Это только мое собственное мнение.

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

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

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

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

1 голос
/ 08 августа 2011

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

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

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

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