jQuery Data vs Attr?

513

Jaka jest różnica w użytkowaniu pomiędzy $.datai $.attrpodczas korzystania data-someAttribute?

Rozumiem, że $.datasą przechowywane w jQuery $.cache, a nie w DOM. Dlatego jeśli chcę używać $.cachedo przechowywania danych, powinienem użyć $.data. Jeśli chcę dodać atrybuty danych HTML5, powinienem użyć $.attr("data-attribute", "myCoolValue").

John B.
źródło
5
proszę przeczytać to: forum.jquery.com/topic/when-to-use-attr-vs-data
Baz1nga
14
@zzz Tyle, że to tak naprawdę nie odpowiada na pytanie ...?
sdleihssirhc
2
Właściwie tak, pośrednio. Dołączenie obiektu przez attr()może prowadzić do wycieków pamięci (przynajmniej w IE), podczas gdy używanie data()jest bezpieczne. Wskazuje na to w swojej odpowiedzi, choć nie wyjawia tego wprost. Więcej informacji na temat dokumentów jQuery (patrz „Dodatkowe uwagi”): api.jquery.com/attr
ken
6
@John B, po prostu FYI (chociaż jest stary), atrybut danych data-someAttributejest niepoprawny; zgodnie ze specyfikacją dozwolone są tylko małe litery. Napotkasz mnóstwo dziwnych problemów, używając wielkich liter.
Ken
1
@AdrienBe Wiele odnośników łatwo znaleźć za pomocą wyszukiwania, ale ponieważ się nudzę, proszę bardzo: stackoverflow.com/a/22753630/84473
Ken

Odpowiedzi:

748

Jeśli przekazujesz dane do elementu DOM z serwera, powinieneś ustawić dane na elemencie:

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

Dostęp do danych można następnie uzyskać .data()w jQuery:

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

Jednak podczas przechowywania danych w węźle DOM w jQuery przy użyciu danych zmienne są przechowywane w obiekcie węzła . Ma to na celu uwzględnienie złożonych obiektów i odniesień, ponieważ przechowywanie danych w elemencie węzła jako atrybutu uwzględni tylko wartości ciągu.

Kontynuując mój przykład z góry:
$('#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

Ponadto konwencja nazewnictwa atrybutów danych zawiera trochę ukrytego „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

Dzielony klucz będzie nadal działał:

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"

Jednak obiekt zwracany przez .data()nie będzie miał ustawionego klucza dzielonego:

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

Z tego powodu sugeruję unikanie klucza dzielonego w javascript.

W przypadku HTML używaj dzielonego formularza. Atrybuty HTML mają dostać ASCII małe litery automatycznie , tak <div data-foobar></div>, <DIV DATA-FOOBAR></DIV>i <dIv DaTa-FoObAr></DiV>niby być traktowane jako identyczne, ale dla najlepszej zgodności powinny być preferowane dolna forma przypadek.

The .data()Metoda będzie również wykonać kilka podstawowych funkcji automatycznego odlewania jeżeli wartość odpowiada uznanym wzór:

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']}`

Ta funkcja automatycznego rzutowania jest bardzo wygodna w przypadku tworzenia widgetów i wtyczek:

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

Jeśli absolutnie musisz mieć oryginalną wartość jako ciąg, musisz użyć .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

To był wymyślony przykład. Do przechowywania wartości kolorów używałem numerycznej notacji szesnastkowej (tj. 0xABC123), ale warto zauważyć, że szesnastka została niepoprawnie przeanalizowana w wersjach jQuery przed 1.7.2 i nie jest już przetwarzana na NumberjQuery 1.8 rc 1.

jQuery 1.8 rc 1 zmieniło zachowanie automatycznego rzucania . Wcześniej każdy format, który był prawidłową reprezentacją pliku, Numberbyłby rzutowany na Number. Teraz wartości liczbowe są rzutowane automatycznie tylko wtedy, gdy ich reprezentacja pozostaje taka sama. Najlepiej ilustruje to przykład.

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"

Jeśli planujesz używać alternatywnych składni numerycznych w celu uzyskania dostępu do wartości liczbowych, pamiętaj, aby rzucić wartość na Numberpierwszą, na przykład za pomocą jednoargumentowego +operatora.

JS (ciąg dalszy):
+$('#foo').data('hex'); // 1000
zzzzBov
źródło
17
@vitorbal, chociaż jest to prawda, obiekt zwracany przez nie.data() będzie miał ustawionej formy dzielonej, więc będzie działać, ale nie będzie. Z tego powodu sugeruję, aby ludzie unikali używania formy dzielonej. $('#bar').data('foo-bar-baz')$('#bar').data()['foo-bar-baz']
zzzzBov
1
ok, teraz rozumiem co masz na myśli. Nie wiedziałem o tym drobnym szczególe, dziękuję za aktualizację :)
vitorbal
1
@SableFoste, który link? api.jquery.com/data jest poprawnym linkiem do metody i nie zmieniłem się, o ile mi wiadomo.
zzzzBov,
1
lubię, foo, bar, baz, fizz, buzz więcej: D
Usman Younas
1
Uwielbiam każdą linię.
Foo Bar
108

Główna różnica między nimi polega na tym, gdzie jest przechowywany i jak jest dostępny.

$.fn.attr przechowuje informacje bezpośrednio na elemencie w atrybutach, które są publicznie widoczne podczas kontroli, a także które są dostępne z natywnego API elementu.

$.fn.dataprzechowuje informacje w absurdalnie niejasnym miejscu. Znajduje się w zamkniętej zmiennej lokalnej o nazwiedata_user która jest instancją lokalnie zdefiniowanej funkcji Data. Ta zmienna nie jest dostępna bezpośrednio z jQuery.

Zestaw danych z attr()

  • dostępny z $(element).attr('data-name')
  • dostępny z element.getAttribute('data-name'),
  • jeżeli wartość była w formie data-namerównież dostępne z $(element).data(name)i element.dataset['name']aelement.dataset.name
  • widoczne na elemencie podczas kontroli
  • nie mogą być przedmiotami

Zestaw danych z .data()

  • dostępne tylko z.data(name)
  • niedostępne z .attr()jakiegokolwiek innego miejsca
  • niewidoczne publicznie na elemencie podczas inspekcji
  • mogą być przedmiotami
Travis J
źródło
2
Tak, moje główne pytanie dotyczyło miejsca przechowywania tych danych, więc dziękuję za te informacje!
Max Wilder
2
Też .attr()jest droga, jeśli potem chcesz użyć danych jako selektor ( .data()nie zostanie znalezione, patrz codepen.io/anon/pen/EvawPV?editors=1011 )
Kamafeather
1

Możesz użyć data-*atrybutu, aby osadzić dane niestandardowe. Te data-*atrybuty daje nam możliwość osadzić danych niestandardowych atrybutów wszystkich elementów HTML.

.data()Metoda jQuery pozwala uzyskać / ustawić dane dowolnego typu do elementów DOM w sposób bezpieczny przed cyklicznymi odniesieniami, a tym samym przed wyciekiem pamięci.

.attr()Metoda jQuery pobiera / ustawia wartość atrybutu tylko dla pierwszego elementu w dopasowanym zestawie.

Przykład:

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

$("#test").attr("title");
$("#test").attr("data-kind");
$("#test").data("kind");
$("#test").data("value", "bar");
Yogendra Chauhan
źródło