.prop() vs .attr()

1942

Итак 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?

UPDATE

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, почему? И как это повлияет на мою кодировку в будущем?

задан Neal 03 мая '11 в 22:33
источник

16 ответов

1675

Обновление 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).
  • Это изменение удаляет часть слоя magic jQuery, застрявшего перед атрибутами и свойствами, что означает, что разработчикам jQuery придется немного узнать о различии между свойствами и атрибутами. Это хорошо.

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

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

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

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

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

На самом деле это самая простая вещь в мире, которая связана с checked Boolean свойством, которое существовало и работало безупречно в каждом главном браузере с возможностью просмотра с 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/.
ответ дан Tim Down 04 мая '11 в 2:06
источник
598

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

Элемент 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" |
| name:       "fooAnchor"                   |
| id:         "fooAnchor"                   |
| className:  "test one"                    |
| attributes:                               |
|    href:  "foo.html"                      |
|    name:  "fooAnchor"                     |
|    id:    "fooAnchor"                     |
|    class: "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.

ответ дан T.J. Crowder 04 мая '11 в 17:27
источник
223

Это изменение было долгое время для 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, чем с самим кодом. Надеюсь, это прояснило вам кое-что.

Матф

ответ дан user1385191 03 мая '11 в 23:05
источник
222

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

Дополнительная информация

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

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

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

изменить

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

ответ дан HerrSerker 27 сент. '11 в 19:55
источник
123

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

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

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

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

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

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

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


.attr vs .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')

ответ дан Gary Green 19 мая '11 в 13:18
источник
42

TL; DR

Используйте prop() более attr() в большинстве случаев.

Свойство - это текущее состояние элемента ввода. Атрибут - это значение по умолчанию.

Свойство может содержать вещи разных типов. Атрибут может содержать только строки

ответ дан agjmills 16 июля '14 в 12:45
источник
31

грязная проверка - пример, где разница наблюдаемая.

Чтобы увидеть это, запустите следующий фрагмент и:

  • нажмите кнопку. Оба флажка были проверены.
  • снимите оба флажка.
  • снова нажмите кнопку. Установлен флажок prop. 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>

Для некоторых атрибутов, таких как disabled on button, добавление или удаление атрибута content disabled="disabled" всегда переключает свойство (называемое атрибутом IDL в HTML5), потому что http://www.w3.org/TR/html5/forms.html#attr-fe-disabled говорит:

Отключенный атрибут IDL должен отражать атрибут отключенного контента.

чтобы вы могли уйти от него, хотя он уродлив, так как он изменяет HTML без необходимости.

Для других атрибутов, таких как checked="checked" на input type="checkbox", все ломается, потому что как только вы нажимаете на него, он становится грязным, а затем добавление или удаление атрибута checked="checked" content больше не отменяет проверочную проверку.

Вот почему вы должны использовать в основном .prop, поскольку он напрямую влияет на эффективное свойство, вместо того чтобы полагаться на сложные побочные эффекты.

ответ дан Ciro Santilli 华涌低端人口 六四事件 法轮功 06 июля '14 в 14:43
источник
29

Все в документе:

Разница между атрибутами и свойствами может быть важной в конкретных ситуациях. Перед jQuery 1.6 метод .attr() иногда учитывал значения свойств при извлечении некоторых атрибутов, что может привести к непоследовательному поведению. Начиная с jQuery 1.6, метод .prop() предоставляет способ явного извлечения значений свойств, в то время как .attr() только извлекает атрибуты.

Итак, используйте prop!

ответ дан Arnaud F. 03 мая '11 в 22:35
источник
24

атрибуты находятся в вашем текстовом документе/файле HTML (== представьте, что это результат анализа разметки html разметки), тогда как свойства находятся в дереве HTML DOM (== в основном фактическое свойство некоторого объекта в смысле JS).

Важно отметить, что многие из них синхронизированы (если вы обновите свойство class, а атрибут class в html также будет обновлен, а в противном случае). Но некоторые атрибуты могут синхронизироваться с неожиданными свойствами - например, атрибут checked соответствует свойству defaultChecked, поэтому

  • ручная проверка флажка изменит значение .prop('checked'), но не изменит значения .attr('checked') и .prop('defaultChecked')
  • настройка $('#input').prop('defaultChecked', true) также изменит .attr('checked'), но это не будет видно на элементе.

Правило большого пальца: .prop() метод должен использоваться для логических атрибутов/свойств и для свойств, которые не существуют в html (например, window.location). Все остальные атрибуты (которые вы можете видеть в html) можно и должно продолжать манипулировать с помощью .attr()метод. (http://blog.jquery.com/2011/05/10/jquery-1-6-1-rc-1-released/)

И вот таблица, в которой показано, где .prop() является предпочтительным (хотя .attr() все еще можно использовать).

table with preferred usage


Почему вы иногда хотите использовать .prop() вместо .attr(), где официально официально заявлено последнее?

  • .prop() может возвращать любой тип - string, integer, boolean; а .attr() всегда возвращает строку.
  • .prop() называется примерно в 2,5 раза быстрее, чем .attr().
ответ дан lakesare 12 июня '15 в 8:56
источник
12

Обычно вы хотите использовать свойства. Использовать атрибуты только для:

  • Получение пользовательского атрибута HTML (поскольку он не синхронизирован с свойством DOM).
  • Получение атрибута HTML, который не синхронизируется с свойством DOM, например. получить "исходное значение" стандартного атрибута HTML, например <input value="abc">.
ответ дан naor 02 февр. '14 в 23:36
источник
11

.attr():

  • Получить значение атрибута для первого элемента в наборе согласованных элементов.
  • Дает вам значение элемента, как оно определено в html на загрузке страницы

.prop():

  • Получить значение свойства для первого элемента в наборе согласованных элементов.
  • Дает обновленные значения элементов, которые изменяются с помощью javascript/jquery
ответ дан Kgn-web 08 дек. '15 в 12:14
источник
6

attributes → HTML

properties → DOM

ответ дан NkS 26 дек. '14 в 16:28
источник
5

Прежде чем jQuery 1.6, метод attr() иногда учитывал значения свойств при извлечении атрибутов, это вызывало довольно противоречивое поведение.

Введение метода prop() обеспечивает способ явного извлечения значений свойств, тогда как .attr() извлекает атрибуты.

Документы:

jQuery.attr() Получите значение атрибута для первого элемента в наборе согласованных элементов.

jQuery.prop() Получить значение свойства для первого элемента в наборе согласованных элементов.

ответ дан Peter.R3x 25 окт. '15 в 3:05
источник
1

Осторожно напоминаем об использовании prop(), например:

if ($("#checkbox1").prop('checked')) {
    isDelete = 1;
} else {
    isDelete = 0;
}

Функция выше используется для проверки флажка checkbox1 или нет, если отмечено: return 1; if not: return 0. Функция prop() используется здесь как функция GET.

if ($("#checkbox1").prop('checked', true)) {
    isDelete = 1;
} else {
    isDelete = 0;
}

Функция выше используется для установки checkbox1 для проверки и возврата ALWAY 1. Теперь функция prop() используется как функция SET.

Не испортите.

P/S: Когда я проверяю свойство src. Если src пуст, prop возвращает текущий URL-адрес страницы (неверно) и attr возвращает пустую строку (справа). p >

ответ дан user2657778 17 окт. '15 в 19:12
источник
0

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

2) $(elem).attr( "checked" ) (1.6.1+) "checked" (String) Будет изменение с состоянием флажка

3) $(elem).attr( "checked" ) (pre-1.6) true (Boolean) Изменено с состоянием флажка

  • В основном мы хотим использовать для объекта DOM вместо пользовательского атрибута например data-img, data-xyz.

  • Также некоторые различия при доступе к значению checkbox и href с attr() и prop() по мере изменения вещи с выходом DOM с prop() в качестве полной ссылки из origin и Boolean значение для флажка (pre-1.6)

  • Мы можем получить доступ только к элементам DOM с помощью prop other, а затем undefined

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"></script>
<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>prop demo</title>
  <style>
    p {
      margin: 20px 0 0;
    }
    b {
      color: blue;
    }
  </style>

</head>

<body>

  <input id="check1" type="checkbox" checked="checked">
  <label for="check1">Check me</label>
  <p></p>

  <script>
    $("input").change(function() {
      var $input = $(this);
      $("p").html(
        ".attr( \"checked\" ): <b>" + $input.attr("checked") + "</b><br>" +
        ".prop( \"checked\" ): <b>" + $input.prop("checked") + "</b><br>" +
        ".is( \":checked\" ): <b>" + $input.is(":checked")) + "</b>";
    }).change();
  </script>

</body>

</html>
ответ дан Parth Trivedi 18 дек. '15 в 12:28
источник
-2

Ответ Gary Hole очень важен для решения проблемы, если код написан таким образом

obj.prop("style","border:1px red solid;")

Так как функция prop возвращает объект CSSStyleDeclaration, код выше не работает должным образом в каком-либо браузере (в моем случае тестируется с IE8 with Chrome Frame Plugin).

Таким образом, изменяя его на следующий код

obj.prop("style").cssText = "border:1px red solid;"

решил проблему.

ответ дан zawhtut 15 окт. '15 в 11:38
источник

Ознакомьтесь с другими вопросами по меткам