jQuery Data vs Attr?


513

Qual è la differenza nell'uso tra $.datae $.attrquando si usa data-someAttribute?

La mia comprensione è che $.dataè memorizzata in jQuery $.cache, non nel DOM. Pertanto, se voglio utilizzare $.cacheper l'archiviazione dei dati, dovrei usare $.data. Se voglio aggiungere attributi di dati HTML5, dovrei usare $.attr("data-attribute", "myCoolValue").



14
@zzz Tranne il fatto che non sembra davvero rispondere alla domanda ...?
sdleihssirhc,

2
In realtà lo fa, indirettamente. Il collegamento di un oggetto tramite attr()può causare perdite di memoria (almeno in IE), mentre l'utilizzo data()è sicuro. Lo accenna nella sua risposta, anche se non viene esplicitamente a dirlo. Maggiori informazioni sui documenti jQuery (consultare le "Note aggiuntive"): api.jquery.com/attr
ken

6
@John B, solo FYI (anche se questo è vecchio), l'attributo data di data-someAttributenon è valido; secondo le specifiche, è consentita solo la minuscola. Incontrerai una miriade di strani problemi usando caratteri maiuscoli.
Ken,

1
@AdrienBe Molti riferimenti facilmente reperibili tramite la ricerca, ma poiché sono annoiato, eccoti qui: stackoverflow.com/a/22753630/84473
ken,

Risposte:


748

Se si stanno passando dati a un elemento DOM dal server, è necessario impostare i dati sull'elemento:

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

È quindi possibile accedere ai dati utilizzando .data()in jQuery:

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

Tuttavia, quando si memorizzano i dati su un nodo DOM in jQuery utilizzando i dati, le variabili vengono archiviate sull'oggetto nodo . Questo per accogliere oggetti complessi e riferimenti memorizzare i dati sul nodo elemento come attributo ospiterà solo valori stringa.

Continuando il mio esempio dall'alto:
$('#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

Inoltre, la convenzione di denominazione per gli attributi dei dati ha un po 'di "gotcha" nascosto:

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

La chiave sillabata funzionerà comunque:

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"

Tuttavia, l'oggetto restituito da .data()non avrà la chiave sillabata impostata:

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

È per questo motivo che suggerisco di evitare la chiave sillabata in javascript.

Per HTML, continua a utilizzare il modulo sillabato. Attributi HTML dovrebbero ottenere ASCII in minuscolo automaticamente , così <div data-foobar></div>, <DIV DATA-FOOBAR></DIV>e <dIv DaTa-FoObAr></DiV>si suppone essere trattati come identici, ma per la migliore compatibilità come minuscole dovrebbero essere preferiti.

Il .data()metodo eseguirà anche alcuni casting automatici di base se il valore corrisponde a un modello riconosciuto:

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

Questa capacità di cast automatico è molto conveniente per creare istanze di widget e plugin:

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

Se devi assolutamente avere il valore originale come stringa, dovrai usare .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

Questo è stato un esempio inventato. Per memorizzare i valori di colore, usavo la notazione esadecimale numerica (cioè 0xABC123), ma vale la pena notare che hex è stato analizzato in modo errato nelle versioni jQuery prima dell'1.7.2 e non è più analizzato in un NumberjQuery 1.8 rc 1.

jQuery 1.8 rc 1 ha modificato il comportamento del casting automatico . In precedenza, veniva Numbereseguito il cast di qualsiasi formato che fosse una rappresentazione valida di a Number. Ora, i valori numerici vengono espressi automaticamente solo se la loro rappresentazione rimane invariata. Questo è meglio illustrato con un esempio.

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"

Se si prevede di utilizzare sintassi numeriche alternative per accedere a valori numerici, assicurarsi di lanciare il valore su un Numberprimo, come con un +operatore unario .

JS (cont.):
+$('#foo').data('hex'); // 1000

17
@vitorbal, mentre questo è vero, l'oggetto restituito da .data()sarà non hanno il set di modulo con trattino, così $('#bar').data('foo-bar-baz')funzionerà, ma $('#bar').data()['foo-bar-baz']non lo farà. È per questo motivo che suggerisco alle persone di evitare l'uso della forma sillabata.
zzzzBov,

1
ok, ora capisco cosa intendi. Non sapevo di quel piccolo dettaglio, grazie per l'aggiornamento :)
vitorbal

1
@SableFoste, quale link? api.jquery.com/data è il collegamento corretto per il metodo e non è cambiato per quanto ne so.
zzzzBov,

1
mi piace, foo, bar, baz, fizz, buzz altro: D
Usman Younas,

1
Adoro ogni linea.
Foo Bar,

108

La differenza principale tra i due è dove viene archiviato e come si accede.

$.fn.attr memorizza le informazioni direttamente sull'elemento in attributi che sono pubblicamente visibili al momento dell'ispezione e che sono disponibili dall'API nativa dell'elemento.

$.fn.datamemorizza le informazioni in modo ridicolmente oscuro luogo . Si trova in una variabile locale chiusa denominata data_userche è un'istanza di una funzione definita localmente Data. Questa variabile non è accessibile direttamente dall'esterno di jQuery.

Set di dati con attr()

  • accessibile da $(element).attr('data-name')
  • accessibile da element.getAttribute('data-name') ,
  • se il valore era in forma data-nameanche accessibile da $(element).data(name)eelement.dataset['name'] eelement.dataset.name
  • visibile sull'elemento al momento dell'ispezione
  • non possono essere oggetti

Set di dati con .data()

  • accessibile solo da.data(name)
  • non accessibile da .attr() o altrove
  • non visibile pubblicamente sull'elemento al momento dell'ispezione
  • possono essere oggetti

2
Sì, la mia domanda principale era dove erano archiviati questi dati, quindi grazie per quelle informazioni!
Max Wilder,

2
È anche .attr()la strada da percorrere, se in seguito si desidera utilizzare i dati come selettore ( .data()non saranno trovati; vedere codepen.io/anon/pen/EvawPV?editors=1011 )
Kamafeather,

1

È possibile utilizzare l' data-*attributo per incorporare dati personalizzati. Gli data-*attributi ci danno la possibilità di incorporare attributi di dati personalizzati su tutti gli elementi HTML.

jQuery .data() metodo consente di ottenere / impostare dati di qualsiasi tipo su elementi DOM in modo sicuro da riferimenti circolari e quindi da perdite di memoria.

.attr()Metodo jQuery ottiene / imposta il valore dell'attributo solo per il primo elemento nel set corrispondente.

Esempio:

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

$("#test").attr("title");
$("#test").attr("data-kind");
$("#test").data("kind");
$("#test").data("value", "bar");
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.