Данные JQuery против Attr?

513

Какая разница в использовании между $.dataи $.attrпри использованииdata-someAttribute ?

Я понимаю, что $.dataхранится в JQuery $.cache, а не в DOM. Поэтому, если я хочу использовать $.cacheдля хранения данных, я должен использовать $.data. Если я хочу добавить атрибуты данных HTML5, я должен использовать $.attr("data-attribute", "myCoolValue").

Джон Б
источник
5
пожалуйста, прочитайте это: forum.jquery.com/topic/when-to-use-attr-vs-data
Baz1nga
14
@zzz За исключением того, что на самом деле он не отвечает на вопрос ...?
sdleihssirhc
2
На самом деле это так, косвенно. Присоединение объекта через attr()может привести к утечке памяти (по крайней мере, в IE), в то время как использование data()безопасно. Он намекает на это в своем ответе, хотя он явно не выходит и не говорит этого. Более подробная информация о документах jQuery (см. «Дополнительные заметки»): api.jquery.com/attr
ken,
6
@John B, просто к вашему сведению (хотя он и старый), атрибут данных data-someAttributeнедействителен; согласно спецификации допускается только нижний регистр. Вы столкнетесь с множеством странных проблем, используя символы верхнего регистра.
Кен
1
@AdrienBe Лота ссылок легко найти с помощью поиска, но, так как мне скучно, вот, пожалуйста: stackoverflow.com/a/22753630/84473
кен

Ответы:

748

Если вы передаете данные в элемент DOM с сервера, вы должны установить данные для элемента:

<a id="foo" data-foo="bar" href="#">foo!</a>

Затем к данным можно получить доступ, используя .data()в jQuery:

console.log( $('#foo').data('foo') );
//outputs "bar"

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

Продолжая мой пример сверху:
$('#foo').data('foo', 'baz');

console.log( $('#foo').attr('data-foo') );
//outputs "bar" as the attribute was never changed

console.log( $('#foo').data('foo') );
//outputs "baz" as the value has been updated on the object

Кроме того, соглашение об именах для атрибутов данных имеет скрытую «погрешность»:

HTML:
<a id="bar" data-foo-bar-baz="fizz-buzz" href="#">fizz buzz!</a>
JS:
console.log( $('#bar').data('fooBarBaz') );
//outputs "fizz-buzz" as hyphens are automatically camelCase'd

Ключ дефиса все еще будет работать:

HTML:
<a id="bar" data-foo-bar-baz="fizz-buzz" href="#">fizz buzz!</a>
JS:
console.log( $('#bar').data('foo-bar-baz') );
//still outputs "fizz-buzz"

Однако у объекта, возвращаемого .data()не будет установлен дефис-ключ:

$('#bar').data().fooBarBaz; //works
$('#bar').data()['fooBarBaz']; //works
$('#bar').data()['foo-bar-baz']; //does not work

Именно по этой причине я предлагаю избегать дефис-ключа в javascript.

Для HTML продолжайте использовать дефисную форму. Атрибуты HTML должны получить ASCII-строчных автоматически , поэтому <div data-foobar></div>, <DIV DATA-FOOBAR></DIV>и <dIv DaTa-FoObAr></DiV>которые предполагаются должны рассматриваться как идентичные, но для лучшей совместимости следует предпочесть нижнюю форму случая.

.data()Метод будет также выполнять некоторые основные автоматического литья , если значение соответствует признанной схеме:

HTML:
<a id="foo"
    href="#"
    data-str="bar"
    data-bool="true"
    data-num="15"
    data-json='{"fizz":["buzz"]}'>foo!</a>
JS:
$('#foo').data('str');  //`"bar"`
$('#foo').data('bool'); //`true`
$('#foo').data('num');  //`15`
$('#foo').data('json'); //`{fizz:['buzz']}`

Эта способность автоматического приведения очень удобна для создания экземпляров виджетов и плагинов:

$('.widget').each(function () {
    $(this).widget($(this).data());
    //-or-
    $(this).widget($(this).data('widget'));
});

Если вам абсолютно необходимо иметь исходное значение в виде строки, то вам нужно использовать .attr() :

HTML:
<a id="foo" href="#" data-color="ABC123"></a>
<a id="bar" href="#" data-color="654321"></a>
JS:
$('#foo').data('color').length; //6
$('#bar').data('color').length; //undefined, length isn't a property of numbers

$('#foo').attr('data-color').length; //6
$('#bar').attr('data-color').length; //6

Это был надуманный пример. Для хранения значений цвета я использовал числовую шестнадцатеричную нотацию (то есть 0xABC123), но стоит отметить, что hex был неправильно проанализирован в версиях jQuery до 1.7.2 и больше не анализируется в NumberjQuery 1.8 rc 1.

jQuery 1.8 RC 1 изменил поведение авто-кастинга . Раньше любой формат, который был допустимым представлением Number, был приведен к Number. Теперь числовые значения автоматически приводятся, только если их представление остается прежним. Это лучше всего иллюстрируется на примере.

HTML:
<a id="foo"
    href="#"
    data-int="1000"
    data-decimal="1000.00"
    data-scientific="1e3"
    data-hex="0x03e8">foo!</a>
JS:
                              // pre 1.8    post 1.8
$('#foo').data('int');        //    1000        1000
$('#foo').data('decimal');    //    1000   "1000.00"
$('#foo').data('scientific'); //    1000       "1e3"
$('#foo').data('hex');        //    1000     "0x03e8"

Если вы планируете использовать альтернативные числовые синтаксисы для доступа к числовым значениям, обязательно приведите значение к Numberпервому, например, с унарным +оператором.

JS (продолжение):
+$('#foo').data('hex'); // 1000
zzzzBov
источник
17
@vitorbal, в то время как это так, объект , возвращаемый .data()будет не иметь дефис набора форм, так $('#bar').data('foo-bar-baz')будет работать, но $('#bar').data()['foo-bar-baz']не будет. Именно по этой причине я предлагаю людям избегать использования дефисной формы.
zzzzBov
1
хорошо, теперь я понимаю, что вы имеете в виду. Не знал об этой маленькой детали, спасибо за обновление :)
vitorbal
1
@SableFoste, какая ссылка? api.jquery.com/data является правильной ссылкой для метода и, насколько я знаю, не изменилась.
zzzzBov
1
Мне нравится, Foo, бар, баз, Fizz, Buzz больше: D
Усман Юнас
1
Люблю каждую строчку.
Foo Bar
108

Основное различие между ними заключается в том, где оно хранится и как к нему обращаются.

$.fn.attr хранит информацию непосредственно об элементе в атрибутах, которые становятся общедоступными при проверке, а также доступны из собственного API элемента.

$.fn.dataхранит информацию в смехотворно неясном месте. Он расположен в закрытой локальной переменной, data_userкоторая называется экземпляром локальной функции Data. Эта переменная не доступна из-за пределов jQuery напрямую.

Набор данных с attr()

  • доступны из $(element).attr('data-name')
  • доступны из element.getAttribute('data-name'),
  • если значение было в форме data-nameтакже доступны из $(element).data(name)и element.dataset['name']иelement.dataset.name
  • виден на элементе при осмотре
  • не может быть объектами

Набор данных с .data()

  • доступны только из.data(name)
  • недоступен из .attr()других мест
  • не виден на элементе при осмотре
  • могут быть объектами
Трэвис Дж
источник
2
Да, мой главный вопрос был, где эти данные хранились, так что спасибо за эту информацию!
Макс Уайлдер
2
Также .attr()это можно сделать, если впоследствии вы захотите использовать данные в качестве селектора ( .data()не будут найдены; см. Codepen.io/anon/pen/EvawPV?editors=1011 )
Kamafeather
1

Вы можете использовать data-*атрибут для встраивания пользовательских данных. Эти data-*атрибуты дают нам возможность встраивать пользовательские атрибуты данных на всех HTML - элементах.

.data()Метод jQuery позволяет вам получать / устанавливать данные любого типа на элементы DOM таким образом, чтобы это было безопасно от циклических ссылок и, следовательно, от утечек памяти.

.attr()Метод jQuery получает / устанавливает значение атрибута только для первого элемента в соответствующем наборе.

Пример:

<span id="test" title="foo" data-kind="primary">foo</span>

$("#test").attr("title");
$("#test").attr("data-kind");
$("#test").data("kind");
$("#test").data("value", "bar");
Йогендра Чаухан
источник