Вопрос: .prop () vs .attr ()


Так jQuery 1.6 имеет новую функцию prop(),

$(selector).click(function(){
    //instead of:
    this.getAttribute('style');
    //do i use:
    $(this).prop('style');
    //or:
    $(this).attr('style');
})

или в этом случае они делают то же самое?

И если я делать переключиться на использование prop(), все старые attr()звонки разрываются, если я переключусь на 1.6?

ОБНОВИТЬ

selector = '#id'

$(selector).click(function() {
    //instead of:
    var getAtt = this.getAttribute('style');
    //do i use:
    var thisProp = $(this).prop('style');
    //or:
    var thisAttr = $(this).attr('style');

    console.log(getAtt, thisProp, thisAttr);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"></script>
<div id='id' style="color: red;background: orange;">test</div>

(см. также эту скрипку: http://jsfiddle.net/maniator/JpUF2/ )

Консоль регистрирует getAttributeкак строку, и attrкак строку, но propкак CSSStyleDeclaration, Зачем? И как это повлияет на мою кодировку в будущем?


2032


источник


Ответы:


Обновление 1 ноября 2012 г.

Мой первоначальный ответ относится конкретно к jQuery 1.6. Мой совет остается тем же, но jQuery 1.6.1 немного изменил ситуацию: перед лицом предсказанной кучи сломанных веб-сайтов команда jQuery вернулся attr()к чему-то близкому (но не точно так же, как) к его старому поведению для логических атрибутов , Джон Ресиг также блог об этом , Я вижу трудности, с которыми они столкнулись, но по-прежнему не согласен с рекомендацией attr(),

Оригинальный ответ

Если вы только когда-либо использовали jQuery, а не DOM напрямую, это может быть запутанным изменением, хотя это, безусловно, концептуально улучшается. Не так хорошо для bazillions сайтов, использующих jQuery, которые сломаются в результате этого изменения.

Я подведу основные вопросы:

  • Вы обычно хотите prop()скорее, чем attr(),
  • В большинстве случаев, prop()делает то, что attr()Привык делать. Замена вызовов на attr()с prop()в вашем коде, как правило, будет работать.
  • Свойства обычно проще иметь дело с атрибутами. Значение атрибута может быть только строкой, тогда как свойство может быть любого типа. Например, checkedсвойство является булевым, styleсвойство - это объект с индивидуальными свойствами для каждого стиля, sizeсвойство - это число.
  • Там, где существует свойство и атрибут с тем же именем, обычно обновление одного будет обновлять другое, но это не относится к некоторым атрибутам входных данных, например valueа также checked: для этих атрибутов свойство всегда представляет текущее состояние, а атрибут (кроме старых версий IE) соответствует значению / проверке ввода по умолчанию (отраженному в defaultValue/ defaultCheckedимущество).
  • Это изменение удаляет некоторый слой волшебного jQuery, застрявшего перед атрибутами и свойствами, что означает, что разработчикам jQuery придется немного узнать о различии между свойствами и атрибутами. Это хорошая вещь.

Если вы разработчик jQuery и путаетесь в этом бизнесе по свойствам и атрибутам, вам нужно сделать шаг назад и немного узнать об этом, поскольку jQuery больше не пытается так сильно защитить вас от этого материала. Для авторитетного, но несколько сухих слов по этому вопросу есть спецификации: DOM4 , HTML DOM , Уровень DOM 2 , Уровень DOM 3 , Документация DOM от Mozilla действительна для большинства современных браузеров и ее легче читать, чем спецификации, поэтому вы можете найти их Ссылка DOM полезно. Есть раздел о свойствах элемента ,

В качестве примера того, как свойства проще обрабатывать, чем атрибуты, рассмотрите флажок, который был первоначально проверен. Вот две возможные части допустимого HTML:

<input id="cb" type="checkbox" checked>
<input id="cb" type="checkbox" checked="checked">

Итак, как вы узнаете, установлен ли флажок с помощью jQuery? Посмотрите на переполнение стека, и вы обычно найдете следующие предложения:

  • if ( $("#cb").attr("checked") === true ) {...}
  • if ( $("#cb").attr("checked") == "checked" ) {...}
  • if ( $("#cb").is(":checked") ) {...}

На самом деле это самая простая вещь в мире, которая связана с checkedBoolean свойство, которое существовало и работало безупречно в каждом главном браузере с возможностью просмотра с 1995 года:

if (document.getElementById("cb").checked) {...}

Свойство также делает проверку или снятие флажка тривиальной:

document.getElementById("cb").checked = false

В jQuery 1.6 это однозначно становится

$("#cb").prop("checked", false)

Идея использования checkedатрибут для скрипта флажок бесполезен и не нужен. Имущество - это то, что вам нужно.

  • Не очевидно, какой правильный способ проверить или снять флажок, используя checkedатрибут
  • Значение атрибута отражает значение по умолчанию, а не текущее видимое состояние (за исключением некоторых старых версий IE, что делает вещи еще сложнее). Атрибут ничего не сообщает о том, установлен ли флажок на странице. Видеть http://jsfiddle.net/VktA6/49/ ,

1724



я думаю Тим сказал это довольно хорошо , но давайте отступим:

Элемент DOM - это объект, объект в памяти. Как и большинство объектов в ООП, свойства , Он также, отдельно, имеет карту атрибутов, определенных на элементе (обычно это происходит из разметки, которую браузер читает для создания элемента). Некоторые из элементов свойства получить их начальная значения из атрибуты с теми же или похожими именами ( valueполучает свое начальное значение из атрибута «значение»; hrefполучает свое начальное значение из атрибута «href», но это не совсем то же значение; classNameиз атрибута «class»). Другие свойства получают свои начальные значения другими способами: например, parentNodeсвойство получает свое значение, исходя из того, каким является его родительский элемент; элемент всегда имеет styleсвойство, имеет ли он атрибут «стиль» или нет.

Рассмотрим этот якорь на странице в http://example.com/testing.html:

<a href='foo.html' class='test one' name='fooAnchor' id='fooAnchor'>Hi</a>

Некоторое безвозмездное ASCII-искусство (и оставляющее много вещей):

+ ------------------------------------------- +
| HTMLAnchorElement |
+ ------------------------------------------- +
| href: "http://example.com/foo.html" |
| имя: "fooAnchor" |
| id: "fooAnchor" |
| className: "test one" |
| атрибуты: |
| href: "foo.html" |
| имя: "fooAnchor" |
| id: "fooAnchor" |
| класс: "test one" |
+ ------------------------------------------- + 

Обратите внимание, что свойства и атрибуты различны.

Теперь, хотя они различны, поскольку все это развивается, а не разрабатывается с нуля, ряд свойств записывается обратно в атрибут, из которого они получены, если вы их установили. Но не все это делают, и, как вы можете видеть из hrefвыше, отображение не всегда является прямым «передать значение», иногда используется интерпретация.

Когда я говорю о свойствах, являющихся свойствами объекта, я не говорю абстрактно. Вот код не-jQuery:

var link = document.getElementById('fooAnchor');
alert(link.href);                 // alerts "http://example.com/foo.html"
alert(link.getAttribute("href")); // alerts "foo.html"

(Эти значения соответствуют большинству браузеров, есть некоторые варианты).

linkобъект - это настоящая вещь, и вы можете видеть, что существует реальное различие между доступом к имущество на нем и доступа к атрибут ,

Как сказал Тим, подавляющее большинство времени мы хотим работать со свойствами. Частично это потому, что их ценности (даже их имена), как правило, более согласованы между браузерами. В основном мы хотим работать с атрибутами, когда нет связанного с ним свойства (пользовательские атрибуты), или когда мы знаем, что для этого конкретного атрибута атрибут и свойство не являются 1: 1 (как в случае с hrefи "href" выше).

Стандартные свойства представлены в различных спецификациях DOM:

Эти спецификации имеют отличные индексы, и я рекомендую сохранять ссылки на них удобными; Я использую их все время.

Пользовательские атрибуты включают, например, любые data-xyzатрибуты, которые вы могли бы поместить на элементы для предоставления метаданных вашему коду (теперь, когда это допустимо с HTML5, если вы придерживаетесь data-префикс). (Последние версии jQuery дают вам доступ к data-xyzэлементов через dataфункции, но эта функция не просто аксессуар для data-xyzатрибуты [он делает все больше и меньше этого]; если вам действительно не нужны его функции, я бы использовал attrфункции для взаимодействия с data-xyzатрибут.)

attrфункция имела обыкновение иметь некоторую запутанную логику вокруг получения того, что они думали, что вы хотели, а не буквально получать атрибут. Он объединил концепции. Переехать в propа также attrпредназначалось для их устранения. Кратко в v1.6.0 jQuery зашел слишком далеко в этом отношении, но функциональность был быстро добавлен назад в attrдля обработки распространенных ситуаций, когда люди используют attrкогда технически они должны использовать prop,


617



Это изменение уже давно наступило для jQuery. В течение многих лет они довольствовались функцией с именем attr()что в основном извлекаются свойства DOM, а не результат, который вы ожидаете от имени. Сегрегация attr()а также prop()должны помочь облегчить некоторую путаницу между атрибутами HTML и свойствами DOM. $.fn.prop()захватывает указанное свойство DOM, тогда как $.fn.attr()захватывает указанный атрибут HTML.

Чтобы полностью понять, как они работают, вот расширенное объяснение различий между атрибутами HTML и свойствами DOM.

Атрибуты HTML

Синтаксис:

<body onload="foo()">

Цель: Позволяет разметке иметь связанные с ней данные для событий, рендеринга и других целей.

Визуализация: HTML AttributesАтрибут класса показан здесь на теле. Он доступен через следующий код:

var attr;
attr = document.body.getAttribute("class");
//IE 8 Quirks and below
attr = document.body.getAttribute("className");

Атрибуты возвращаются в виде строки и могут быть непоследовательными от браузера к браузеру. Однако они могут быть жизненно важными в некоторых ситуациях. Как показано выше, IE Quirks Mode (и ниже) ожидает имя свойства DOM в get / set / removeAttribute вместо имени атрибута. Это одна из многих причин, почему важно знать разницу.

Свойства DOM

Синтаксис:

document.body.onload = foo;

Цель: Предоставляет доступ к свойствам, которые принадлежат узлам элемента. Эти свойства похожи на атрибуты, но доступны только через JavaScript. Это важное различие, которое помогает выяснить роль свойств DOM. Обратите внимание, что атрибуты полностью отличаются от свойств , поскольку это назначение обработчика события бесполезно и не получит событие (тело не имеет события onload, только атрибут onload).

Визуализация: DOM Properties

Здесь вы увидите список свойств на вкладке «DOM» в Firebug. Это свойства DOM. Вы сразу заметите немало из них, поскольку вы будете использовать их раньше, не зная об этом. Их значения - это то, что вы будете получать через JavaScript.

Документация

пример

HTML: <textarea id="test" value="foo"></textarea>

JavaScript: alert($('#test').attr('value'));

В более ранних версиях jQuery это возвращает пустую строку. В 1.6 он возвращает правильное значение, foo,

Не взглянув на новый код для любой функции, я могу с уверенностью сказать, что путаница больше связана с различием между атрибутами HTML и свойствами DOM, чем с самим кодом. Надеюсь, это прояснило вам кое-что.

Матф


231



Свойство находится в DOM; атрибут находится в HTML, который анализируется в DOM.

Дальнейшие детали

Если вы измените атрибут, это изменение будет отражено в DOM (иногда с другим именем).

Пример: изменение classатрибут тега изменит classNameсвойство этого тега в DOM. Если у вас нет атрибута в теге, у вас все еще есть соответствующее свойство DOM с пустым или значением по умолчанию.

Пример. Пока у вашего тега нет classатрибут, свойство DOM classNameсуществует с пустым строковым значением.

редактировать

Если вы измените одно, другое будет изменено контроллером и наоборот. Этот контроллер не находится в jQuery, но в собственном коде браузера.


229



Это просто различие между атрибутами HTML и объектами DOM, которые приводят к путанице. Для тех, кто удобен в отношении свойств свойств DOM-элементов, таких как this.src this.value this.checkedи т.д, .propэто очень теплый прием в семье. Для других это просто дополнительный путаница. Поясним это.

Самый простой способ увидеть разницу между .attrа также .propявляется следующим примером:

<input blah="hello">
  1. $('input').attr('blah'): возвращает 'hello'как и ожидалось. Здесь нет сюрпризов.
  2. $('input').prop('blah'): возвращает undefined- потому что он пытается это сделать [HTMLInputElement].blah- и никакого такого свойства на этом объекте DOM не существует. Он существует только в области как атрибут этого элемента, т.е. [HTMLInputElement].getAttribute('blah')

Теперь мы изменим несколько таких вещей:

$('input').attr('blah', 'apple');
$('input').prop('blah', 'pear');
  1. $('input').attr('blah'): возвращает 'apple'а? Почему бы не «груша», поскольку это было последним для этого элемента. Поскольку свойство было изменено на входном атрибуте, а не на элемент ввода DOM - они практически работают независимо друг от друга.
  2. $('input').prop('blah'): возвращает 'pear'

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

См. Скрипку, демонстрирующую разницу: http://jsfiddle.net/garreh/uLQXc/


.attrпротив .prop:

Раунд 1: стиль

<input style="font:arial;"/>
  • .attr('style')- возвращает встроенные стили для согласованного элемента i.e. "font:arial;"
  • .prop('style')- возвращает объект объявления стиля i.e. CSSStyleDeclaration

Круглый 2: стоимость

<input value="hello" type="text"/>   

$('input').prop('value', 'i changed the value');
  • .attr('value')- возвращает 'hello'*
  • .prop('value')- возвращает 'i changed the value'

* Примечание: jQuery по этой причине имеет .val()метод, который внутренне эквивалентен .prop('value')


128



TL;DR

Use prop() over attr() in the majority of cases.

A property is the current state of the input element. An attribute is the default value.

A property can contain things of different types. An attribute can only contain strings


46



All is in the doc :

The difference between attributes and properties can be important in specific situations. Before jQuery 1.6, the .attr() method sometimes took property values into account when retrieving some attributes, which could cause inconsistent behavior. As of jQuery 1.6, the .prop() method provides a way to explicitly retrieve property values, while .attr() only retrieves attributes.

So use prop !


31



dirty checkedness is an example where the difference is observable.

To see it, run the following snippet and:

  • click the button. Both checkboxes got checked.
  • uncheck both checkboxes.
  • click the button again. Only the prop checkbox got checked. BANG!

$('button').on('click', function() {
  $('#attr').attr('checked', 'checked')
  $('#prop').prop('checked', true)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label>attr <input id="attr" type="checkbox"></label>
<label>prop <input id="prop" type="checkbox"></label>
<button type="button">Set checked attr and prop.</button>

For some attributes like disabled on button, adding or removing the content attribute disabled="disabled" always toggles the property (called IDL attribute in HTML5) because http://www.w3.org/TR/html5/forms.html#attr-fe-disabled says:

The disabled IDL attribute must reflect the disabled content attribute.

so you might get away with it, although it is ugly since it modifies HTML without need.

For other attributes like checked="checked" on input type="checkbox", things break, because once you click on it, it becomes dirty, and then adding or removing the checked="checked" content attribute does not toggle checkedness anymore.

This is why you should use mostly .prop, as it affects the effective property directly, instead of relying on complex side-effects.


31



attributes are in your HTML text document/file (== imagine this is the result of your html markup parsed), whereas
properties are in HTML DOM tree (== basically an actual property of some object in JS sense).

Importantly, many of them are synced (if you update class property, class attribute in html will also be updated; and otherwise). But some attributes may be synced to unexpected properties - eg, attribute checked corresponds to property defaultChecked, so that

  • manually checking a checkbox will change .prop('checked') value, but will not change .attr('checked') and .prop('defaultChecked') values
  • setting $('#input').prop('defaultChecked', true) will also change .attr('checked'), but this will not be visible on an element.

Rule of thumb is: .prop() method should be used for boolean attributes/properties and for properties which do not exist in html (such as window.location). All other attributes (ones you can see in the html) can and should continue to be manipulated with the .attr() method. (http://blog.jquery.com/2011/05/10/jquery-1-6-1-rc-1-released/)

And here is a table that shows where .prop() is preferred (even though .attr() can still be used).

table with preferred usage


Why would you sometimes want to use .prop() instead of .attr() where latter is officially adviced?

  1. .prop() can return any type - string, integer, boolean; while .attr() always returns a string.
  2. .prop() is said to be about 2.5 times faster than .attr().

25



.attr():

  • Get the value of an attribute for the first element in the set of matched elements.
  • Gives you the value of element as it was defines in the html on page load

.prop():

  • Get the value of a property for the first element in the set of matched elements.
  • Gives the updated values of elements which is modified via javascript/jquery

16



Usually you'll want to use properties. Use attributes only for:

  1. Getting a custom HTML attribute (since it's not synced with a DOM property).
  2. Getting a HTML attribute that doesn't sync with a DOM property, e.g. get the "original value" of a standard HTML attribute, like <input value="abc">.

12



attributes -> HTML

properties -> DOM


6