Разработайте причину взаимосвязи между свойством элемента и его соответствующим атрибутом

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

Ниже приведен график из jquery in action 2015 Bear Bibeault книги jquery in action 2015 Bear Bibeault, показывающий взаимосвязь между property и attribute элемента DOM.

enter image description here

Чтобы дополнительно объяснить концепцию, у автора был следующий код и пояснения для кода.

enter image description here

enter image description here

Мой вопрос: почему некоторые property и attribute синхронизируются, почему некоторые из них не синхронизированы и почему некоторые attributes не имеют соответствующего property?

Я нашел отличный пост, объясняющий взаимосвязь между property и attribute, но он не касался того, почему он был разработан таким образом. Я надеюсь понять причины, лежащие в основе дизайна.

Связанный вопрос, если я хочу получить или установить значение в элементе DOM, должен ли я получить/установить property или attribute?

И как мы находим связь между конкретным property и его соответствующим attribute когда нам нужно? Есть ли документация, в которой подробно описываются отношения?

Ответы

Ответ 1

Вы найдете ответы, скрытые в HTML-спецификациях. Сначала я хочу, чтобы вы взглянули на атрибуты и свойства элемента input (заголовок "Атрибуты контента" и "Интерфейс DOM") и раздел об отражении атрибутов (первый абзац).

Вы заметите, что все атрибуты имеют соответствующие свойства, а управление свойством изменяет атрибут, который он отражает. Стоит отметить, что:

(1) Атрибут может отражаться на свойстве с немного другим именем. Классическим примером является class атрибут, который отражается от className собственности и for атрибута, который отражается от htmlFor собственности.

(2) Аналогично, checked атрибут отражается свойством defaultChecked тогда как checked свойство представляет внутреннее состояние флажка независимо от checked атрибута. Это всегда вызывало путаницу среди программистов (и авторов книг). Разница объясняется в конце этого ответа.

(3) Приведенные атрибуты (например, атрибут "книга" в вашем примере) не будут создавать соответствующее свойство и наоборот. С этой целью спецификации HTML описывают механизм, называемый атрибутами dataset свойством dataset.

Связанный вопрос, если я хочу получить или установить значение в элементе DOM, должен ли я получить/установить property или attribute?

Зависит. Например, оба следующих результата дают идентичный результат и HTML:

document.getElementById("div-1").title = "Hello";
document.getElementById("div-1").setAttribute("title") = "Hello";

Однако для элементов формы вы должны манипулировать состоянием, а не атрибутом. Предположим, у вас есть эта разметка HTML:

<input type="checkbox" id="checkbox-1">

И вы выполните одно из следующих действий:

document.getElementById("checkbox-1").defaultChecked = true;
document.getElementById("checkbox-1").setAttribute("checked", "checked");

И вот результат:

<input type="checkbox" id="checkbox-1" checked="checked">

Но проверяется, действительно ли флажок установлен, зависит от загрязненности элемента управления (т.е. Если его состояние было изменено в какой-то момент). Для элементов формы вы обычно управляете свойствами, соответствующими внутреннему состоянию:

document.getElementById("checkbox-1").checked = true;

Ответ 2

DOM - это то, что в значительной степени выросло "естественно". Вы должны учитывать, что HTML (значение: атрибуты) на первом месте, и первоначально не было никаких скриптов. В конце концов, Netscape представил JavaScript с тем, что вы считаете крайне ограниченным API сегодня. Этот API был направлен на манипулирование формами, а не на произвольные HTML-элементы. И затем Netscape и Internet Explorer вышли с различными вариантами того, что они называли DHTML, тогда (Dynamic HTML). Вариант Netscape опирался на специальный <layer> и никто его не помнит сегодня. Вариант Internet Explorer допускал более общий доступ к элементам HTML и, в частности, имел отображение свойств атрибутов 1:1.

Хотя Internet Explorer выиграл эту войну, ее вариант DHTML был разработан, когда люди думали об именах атрибутов HTML как фиксированной коллекции. С произвольными атрибутами у него было слишком много проблем. Например:

  • Атрибут class не может быть сопоставлен с JavaScript изначально, потому что class является зарезервированным ключевым словом. Хотя последующие изменения в стандарте JavaScript допускали использование зарезервированных ключевых слов в качестве имен свойств, Internet Explorer должен сопоставить атрибут class с свойством className. Установка атрибута className для элемента или свойства el["class"] на объекте JavaScript приводила к смешным несоответствиям.
  • Атрибуты HTML не чувствительны к регистру, а свойства JavaScript чувствительны к регистру. Таким образом, у Internet Explorer были всевозможные хаки, чтобы признать намерение. Что произошло, когда элемент был <FOO SOMEATTIRIBUTE> и вы пытались получить доступ к el.someAttribute или el.SOMEATTRIBUTE из JavaScript? Я больше не помню, но это было некрасиво.
  • Объекты JavaScript всегда имеют методы. Например, атрибут toString не может быть сопоставлен с свойством, поскольку он маскирует метод toString().

Ни один браузер, кроме Internet Explorer, никогда не реализовал это сопоставление атрибутов свойствам 1:1, и даже Internet Explorer отказался от него, как только это было возможно с точки зрения обратной совместимости (это заняло очень много времени). Вместо этого атрибуты и свойства теперь рассматриваются как отдельные пространства имен. Браузеры предоставят вам некоторые свойства в качестве ярлыков для доступа к атрибутам и манипуляций, но они действительно доступны только для вашего удобства. И есть некоторые обратные случаи совместимости, загрязняющие воды: атрибут value и атрибут value фактически не сопоставляются друг с другом, первый отражает текущее состояние элемента, тогда как последнее отражает его начальное состояние.

Изменить: просто для справки вы приводите следующее выражение:

Если атрибут существует как встроенное свойство, но он имеет значение Boolean, значение не синхронизируется.

Это неправильно, поведение не имеет ничего общего с булевыми против строк. Как упоминалось выше, свойство value аналогично отсутствует синхронизация с checked свойством. С другой стороны, логическое hidden свойство будет соответствующим образом синхронизироваться с соответствующим атрибутом. Из того, что я могу сказать, вы найдете отсутствующую синхронизацию между свойством и атрибутом вокруг оригинальных API-интерфейсов обработки форм, которые были введены Netscape - это просто обратная совместимость.

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