2015-03-23 12 views
5

Io in genere evitare di dover includere la libreria jQuery nei miei scritti, ma ho solo recentemente sono imbattuto in jQuery $ .data() 's funzioni possibilità di associare i dati, sotto forma di coppie di valori chiave, oggetti & anche le funzioni, con qualsiasi elemento.

Da quello che ho letto, la funzione $ .data() di jQuery ha anche protezioni incorporate che prevengono la perdita di memoria associata a tali pratiche, ma è eccessivo includere l'intera libreria JQ per quella singola funzione.

Qualcuno sa di un'alternativa nativa?

EDIT per farmi più chiaro, non sto cercando la funzione nativa per recuperare gli attributi degli elementi. $ .data() API di jQuery va ben oltre tale utilizzo, che si estende per la sua capacità di associare oggetti JavaScript & funzioni con nodi elemento jQuery.

Questo articolo (http://tutorialzine.com/2010/11/jquery-data-method/) tocca questo utilizzo, ma come esempio lo sto attualmente utilizzando per associare un'animazione della linea temporale GSAP a un oggetto, in modo che possa accedere e chiamare la funzione di animazione .reverse() di GSAP Timeline all'esterno di la funzione che è stata creata. Per esempio:

function doAnimation(){ 
    var element = document.createElement('div'), 
     timeline = new TimelineMax({....GSAP related fns...}), 
     options = { 
      .... 
      timeline: timeline 
     }; 
    $(element).data('options', options); 
} 


function reverseAnimation($element){ 
    var options = $element.data('options'), 
     previouslyCreatedTimeline = options.timeline; 

    previouslyCreatedTimeline.reverse(); 
} 

Forse non l'esempio più chiaro, se non sei un utente di GSAP, ma in sostanza, il metodo $ .data() mi ha permesso di associare un oggetto JavaScript con un elemento, in modo che io può accedere ai suoi metodi in una funzione al di fuori del suo ambito originale.

+0

possibile duplicato di [Imposta attributo dati utilizzando JavaScript] (http://stackoverflow.com/questions/11286661/set-data-attribute-using-javascript) – DrCord

+0

No, non un duplicato. Sebbene il metodo della funzione dati di jquery sia utilizzato principalmente per attributi di dati attualmente su un elemento, sto parlando del suo utilizzo per associarlo a oggetti javascript effettivi – AJeezy9

+0

Perché non puoi semplicemente fare qualcosa come 'document.getElementById (" foo "). bar = {baz: function() {}} '? –

risposta

1

utilizzare il metodo setAttribute:

document.getElementById('item1').setAttribute('data', "icon: 'base2.gif', url: 'output.htm', target: 'AccessPage', output: '1'"); 

Ma davvero dovrebbe essere utilizzando i dati seguita con un trattino e con la proprietà, come:

<li ... data-icon="base.gif" ...> 

E per farlo in JS utilizzare il set di dati Proprietà:

document.getElementById('item1').dataset.icon = "base.gif"; 
+0

Apprezzo la tua risposta, ma ti preghiamo di vedere sopra la modifica per una spiegazione più chiara del motivo per cui questa non è la risposta corretta. Cercherò l'articolo che meglio spiega questo utilizzo e linkalo quando ho tempo. – AJeezy9

+0

Sembra che tu stia chiedendo come fare qualcosa che è incorporato in javascript di base ... aggiungendo più dati a un oggetto ... forse dovresti chiarire esattamente cosa intendi per "dati associati, sotto forma di coppie di valori chiave , oggetti e persino funzioni, con qualsiasi elemento. " – DrCord

+0

Capisco la confusione. In alto, ho collegato a un articolo e fornito il mio caso di utilizzo del mio esempio nel tentativo di aiutarti a capire meglio. Vorrei che la domanda avrebbe potuto essere scritta più chiaramente per evitare confusione, ma non potevo pensare a un modo migliore. – AJeezy9

2

Vedere la seguente funzione di dati generici. Utilizzare $.data(obj) per ottenere tutti i metadati attribuiti a qualsiasi oggetto, $.data(obj, key) per ottenere i metadati con una data chiave attribuito ad un oggetto, e $.data(obj, key, val) per impostare i metadati con una data chiave per un oggetto. Ci possono essere problemi con le collisioni di attributi degli oggetti nativi come impostazione di qualcosa con una chiave di 'toString' o 'hasOwnProperty'.

window.$ = { 
    data: function(obj, key, val) { 
     if(!obj) { 
      return this._data; 
     } else if(!key) { 
      if(!(obj in this._data)) { 
       return {}; 
      } 
      return this._data[obj]; 
     } else if(arguments.length < 3) { 
      if(!(obj in this._data)) { 
       return undefined; 
      } 
      return this._data[obj][key]; 
     } else { 
      if(!(obj in this._data)) { 
       this._data[obj] = {}; 
      } 
      this._data[obj][key] = val; 
     } 
    }, 
    _data: {} 
}; 

Ecco un esempio di come si utilizza:

$.data(document.body); // Returns {} because no data has been set for this object 
$.data(document.body, 'lastUpdate', new Date());//Sets 'lastUpdate' of obj to current time 
$.data(document.body, 'lastUpdate'); // Gets previously set time 
$.data(document.body); // Gets object of all data, including 'lastUpdate' time 
$.data(document.body, 'nonexistant'); // Returns undefined because property was never set 
$.data(); // Returns all metadata 
+0

Questa soluzione sembra perdere memoria. – Bergi

+0

Questa sembra la soluzione migliore. Come fai a sapere che ha una perdita di memoria? Fissare la perdita di memoria su questa sarebbe la soluzione migliore. – DrCord

+0

Per evitare conflitti di nomi, sarebbe opportuno utilizzare un 'Simbolo' al posto di' _data' –

1

Per immagazzinaggio semplice valore-chiave, utilizzare .dataset, che riflette le data-* attributi dell'elemento. Tuttavia, è limitato ai valori stringa, pertanto è necessario serializzare i valori compositi (ad esempio utilizzando JSON).

Per memorizzare riferimenti a oggetti e funzioni, si consiglia di utilizzare WeakMap. Si prenderà cura di evitare perdite di memoria. Nel browser che non supporta questo, è sufficiente archiviarli come proprietà diretta sull'elemento html, ma fare attenzione a scegliere i nomi di proprietà privi di collisione.

2

È possibile memorizzare qualsiasi cosa su qualsiasi elemento DOM:

// store data: 
document.body.data = {a:1, b:2}; 

// retrieve data: 
console.log(document.body.data); 

ho usato la parola data qui come una proprietà DOM personalizzata, ma può essere qualsiasi parola che non sia già in uso.


jQuery non memorizza le cose sugli elementi stessi, perché può portare a perdite di memoria, ma dal momento che hai bisogno di questo per un compito ben preciso, allora questo dovrebbe funzionare. Assicurati solo di sapere come funzionano le perdite di memoria prima di provare questo.

Le altre risposte menzionavano l'attributo HTML data. Questo non ha nulla a che fare con jQuery data. Assolutamente nulla, e richiede anche di analizzare e stringere i dati (se non è già una stringa).

+0

Nella speranza di non essere indirizzati a Google, qualsiasi risorsa di qualità a cui è possibile collegare per capire le perdite di memoria? Perché posso pensare a molti modi di memorizzare dati variabili in una finestra, ma la perdita di memoria è la ragione principale per cui ho fatto questa domanda. Immagino che sia solo uno di quegli argomenti che so essere incredibilmente importanti per le prestazioni, ma che sono anche un po 'mitici su come/quando/perché accade. – AJeezy9

+0

@ AJeezy9 - beh, se si rimuove un elemento e quell'elemento utilizza la tecnica sopra e i dati su quell'elemento eliminato puntano su un altro elemento DOM, allora ciò potrebbe causare una perdita di memoria. – vsync

1

Ho scritto un wrapper su WeakMap e Map, che dovrebbe fare il lavoro. La cosa bella di WeakMap è che il valore ottiene GarbageCollected, una volta eliminato l'elemento. Questo dovrebbe evitare perdite di memoria.

/** A storage solution aimed at replacing jQuerys data function. 
* Implementation Note: Elements are stored in a (WeakMap)[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap]. 
* This makes sure the data is garbage collected when the node is removed. 
*/ 
window.dataStorage = { 
    _storage: new WeakMap(), 
    put: function (element, key, obj) { 
     if (!this._storage.has(key)) { 
      this._storage.set(element, new Map()); 
     } 
     this._storage.get(element).set(key, obj); 
    }, 
    get: function (element, key) { 
     return this._storage.get(element).get(key); 
    }, 
    has: function (element, key) { 
     return this._storage.get(element).has(key); 
    }, 
    remove: function (element, key) { 
     var ret = this._storage.get(element).delete(key); 
     if (!this._storage.get(key).size === 0) { 
      this._storage.delete(element); 
     } 
     return ret; 
    } 
} 

usare in questo modo:

var myElement = document.getElementById("myId"); 
dataStorage.put(myElement, "myKey", "myValue"); 

Questo è molto più veloce di $ .data(), ma ancora un po 'più lento di memorizzazione delle informazioni come una proprietà a un elemento.