JQuery Data vs Attr?
В чем разница между использованием $.data
и $.attr
при использовании data-someAttribute
?
Я понимаю, что $.data
хранится в jQuery $.cache
, а не в DOM. Поэтому, если я хочу использовать $.cache
для хранения данных, я должен использовать $.data
. Если я хочу добавить атрибуты данных HTML5, я должен использовать $.attr("data-attribute", "myCoolValue")
.
Ответы
Ответ 1
Если вы передаете данные в элемент DOM с сервера, вы должны установить данные в элементе:
<a id="foo" data-foo="bar" href="#">foo!</a>
Затем данные можно получить с помощью .data()
в jQuery:
console.log( $('#foo').data('foo') );
//outputs "bar"
Однако, когда вы храните данные на DOM node в jQuery с использованием данных, переменные сохраняются в объекте node. Это относится к сложным объектам и ссылкам как к хранению данных в элементе node, поскольку атрибут будет содержать только строковые значения.
Продолжая мой пример сверху:$('#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
Кроме того, соглашение об именах для атрибутов данных имеет немного скрытого "gotcha":
<Суб > 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, и больше не анализируется на Number
как на jQuery 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
Ответ 2
Основное различие между ними заключается в том, где он хранится и как он доступен.
$.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()
или где-либо еще
- не является общедоступным для элемента при проверке
- могут быть объектами
Ответ 3
Ответ не так прост и требует некоторых объяснений.
Посмотрите, что документация jQuery говорит об этих двух методах:
.data()
Храните произвольные данные, связанные с указанным элементом, и/или возвращайте значение, которое было установлено.
и
.attr()
Получить значение атрибута для первого элемента в наборе согласованных элементов или установить один или несколько атрибутов для каждого согласованного элемента.
Разница между .data() и .attr()
В основном метод .attr() оказывает прямое влияние на DOM, поэтому он будет получать данные из текущего HTML или изменить код HTML, если используется для изменения значения атрибута. Contrariwise, метод .data() получит данные из внутреннего кеша и изменит эти данные, если вызван набор, здесь не выполняется манипуляция DOM. Другое отличие состоит в том, что метод .data() требует, чтобы префикс "data-" работал, например, если я хочу передать атрибут данных с именем foo с баром в качестве значения, которое я должен кодировать: data-foo = "bar" и вызовите $('# item'). data ('foo'), чтобы получить значение.
Как я уже сказал, хранение данных во внутреннем кеше не отображается внутри DOM (например, проверка элемента с помощью браузера), это означает, что если у нас есть атрибут data-foo, и мы меняем его с помощью .attr(), его значение, полученное с помощью .data(), будет таким же, как и исходное. Хорошо, вероятно, эта часть немного запутанна. Я сделал короткий код JSFiddle, который помогает понять его.
В моем примере есть простой div:
<div id="item" data-foo="bar"></div>
Элемент, называемый div, имеет атрибут data-foo, который мы будем редактировать двумя способами: с .attr() и с .data().
В результате получится следующее:
data-foo from data(): bar
data-foo from attr(): bar
-
data changed to bar2
-
data-foo from data(): bar2
data-foo from attr(): bar
-
<div id="item" data-foo="bar"> </div>
-
attribute changed to bar3
-
data-foo from data(): bar2
data-foo from attr(): bar3
-
<div id="item" data-foo="bar3"> </div>
Как объяснялось ранее, вызов .data() для установки чего-то не будет управлять файлом dom, а вызов .attr() для изменения атрибута не изменит данные внутри внутреннего кеша.
Это означает, что мы не можем изменить атрибут с использованием .attr() и ожидать, что данные возвращаются из вызова .data().
Хорошо, теперь это немного более понятно, но где .data() лучше, чем .attr() или наоборот?
Теперь, когда различия между .data() и .attr() ясны, мы можем понять, когда лучше использовать .attr() и когда лучше использовать .data().
Хорошее использование вызова .data() - это когда значение передается клиенту с сервера, который отображает страницу. Например, если у нас есть веб-приложение, которому нужно передать значение foo клиенту, внутри нашего механизма рендеринга у нас будет что-то вроде:
<div data-foo='<%=item.foo%>'>
Хорошим преимуществом .data() over.attr() является то, что переменные хранятся в объекте node, поэтому мы можем хранить сложные объекты, а не только строковые значения. Таким образом, это означает, что .data() - лучший способ хранения данных, когда мы должны получать/устанавливать данные относительно текущего состояния нашего приложения.
Вызов .attr() лучше, когда мы имеем дело с изменениями в дереве DOM, которые будут иметь прямое влияние на разметку, например, если нам нужно иметь дело с флажком, где атрибут "checked" будет фактически показывать этот флажок установлен в пользовательском интерфейсе. Пример JSFiddle.
Ответ 4
Вы можете использовать data-*
для встраивания пользовательских данных. data-*
дают нам возможность встраивать пользовательские атрибуты данных во все элементы HTML.
Метод jQuery .data()
позволяет вам получать/устанавливать данные любого типа для элементов DOM способом, который защищен от циклических ссылок и, следовательно, от утечек памяти.
.attr()
jQuery .attr()
получает/устанавливает значение атрибута только для первого элемента в соответствующем наборе.
Пример:
<span id="test" title="foo" data-kind="primary">foo</span>
$("#test").attr("title");
$("#test").attr("data-kind");
$("#test").data("kind");
$("#test").data("value", "bar");