Lavorare con IndexedDB - Parte 2

Benvenuti alla seconda parte del mio articolo IndexedDB. io fortemente consiglio di leggere il primo articolo di questa serie, poiché presumo che tu abbia familiarità con tutti i concetti trattati finora. In questo articolo, riassumeremo gli aspetti CRUD che non abbiamo terminato prima (specificamente l'aggiornamento e l'eliminazione dei contenuti), e quindi dimostreremo un'applicazione reale che useremo per dimostrare altri concetti nell'articolo finale.


Aggiornamento dei record

Iniziamo discutendo su come aggiornare un record con IndexedDB. Se ricordi, l'aggiunta di dati è stata piuttosto semplice:

// Definisci una persona var person = nome: nome, email: email, creato: new Date () // Esegui l'aggiunta var request = store.add (person);

L'aggiornamento di un record è altrettanto semplice. Supponendo di aver definito una proprietà chiamata id come chiave per il tuo negozio di oggetti, puoi semplicemente usare il mettere metodo invece di Inserisci.

var person = nome: nome, email: email, creato: new Date (), id: someId // Esegue l'aggiornamento var request = store.put (person);

Come il Inserisci metodo, è possibile assegnare metodi per gestire i risultati asincroni dell'operazione.


Eliminazione di record

L'eliminazione dei record avviene tramite il metodo delete. (Grande sorpresa lì.) Basta passare l'identificatore univoco del record che si desidera rimuovere. Qui c'è un semplice esempio:

 var t = db.transaction (["persone"], "readwrite"); var request = t.objectStore ("people"). delete (thisId);

E come ogni altro aspetto di IndexedDB, puoi aggiungere gli handle per i risultati asincroni.

Quindi, come ho detto, non terribilmente eccitante, che è probabilmente buono. Vuoi che le tue API siano semplici, noiose e non sorprendenti. Ora prendiamo ciò che abbiamo imparato e riuniamolo per creare un'applicazione reale, se semplice.


L'App Note

Ok, finalmente abbiamo tutte (beh, la maggior parte) delle parti di cui abbiamo bisogno per costruire una vera applicazione. Dal momento che non è stato fatto prima (ahem), costruiremo una semplice nota per l'applicazione. Diamo un'occhiata ad alcune schermate e poi ti mostrerò il codice dietro di esso. All'avvio, l'applicazione inizializza un IndexedDB per l'applicazione e esegue il rendering di una tabella vuota. Inizialmente, tutto ciò che puoi fare con l'applicazione è aggiungere una nuova nota. (Potremmo rendere questo un po 'più user friendly forse.)


Cliccando sul Aggiungi nota pulsante apre un modulo:


Dopo aver inserito alcuni dati nel modulo, è possibile salvare la nota:


Come puoi vedere, hai la possibilità di modificare ed eliminare le note. Infine, se fai clic sulla riga stessa, puoi leggere la nota:


Quindi non esattamente scienza missilistica, ma un completo esempio funzionante delle specifiche IndexedDB. Le note scritte qui rimarranno. Puoi chiudere il browser, riavviare la macchina, prendere qualche anno di pausa per contemplare la vita e la poesia, e quando riapri il browser i tuoi dati saranno ancora lì. Diamo un'occhiata al codice ora.

Primo: un disclaimer. Questa applicazione sarebbe stata un candidato perfetto per uno dei molti framework JavaScript. Sono sicuro che quelli di voi che usano Backbone o Angular possono già immaginare come si configurerebbe. Tuttavia, ho fatto la coraggiosa decisione qui non usa un framework. Ero preoccupato sia delle persone che potrebbero usare un quadro diverso che di quelli che non ne usano. Volevo che il nostro focus qui fosse sugli aspetti IndexedDB da solo. Mi aspetto che alcune persone non siano d'accordo con questa decisione, ma lasciamolo sfogare nei commenti.

Il nostro primo modello è il file HTML. Ne abbiamo solo uno e la maggior parte di questi è Bootplrap di tipo boilerplate:

     Note Database     
Note Database

Modifica nota

Come accennato in precedenza, una porzione di dimensioni di questo file è il codice di modello per Bootstrap. Le parti che ci interessano sono le noteList div, il noteDetail div, e il noteForm. Probabilmente puoi indovinare che questi sono i DIV che aggiorneremo mentre l'utente fa clic nell'applicazione.

Codifica il nostro file di app principale

Ora diamo un'occhiata a app.js, il file principale che gestisce la logica per la nostra applicazione.

/ * console globale, $, documento, finestra, avviso * / var db; function dtFormat (input) if (! input) return ""; var res = (input.getMonth () + 1) + "/" + input.getDate () + "/" + input.getFullYear () + ""; var hour = input.getHours (); var ampm = "AM"; if (hour === 12) ampm = "PM"; se (ora> 12) ora- = 12; ampm = "PM";  var minute = input.getMinutes () + 1; if (minuto < 10) minute = "0" + minute; res += hour + ":" + minute + " " + ampm; return res; 

È possibile ignorare la prima funzione in quanto è semplicemente un'utilità di formattazione per le date. Andiamo avanti al blocco di documenti pronti jQuery.

Verifica del supporto del browser

 $ (document) .ready (function () if (! ("indexedDB" nella finestra)) alert ("Richiesto IndexedDB richiesto per questa dimostrazione!"); return; var $ noteDetail = $ ("# noteDetail") ; var $ noteForm = $ ("# noteForm"); var openRequest = window.indexedDB.open ("nettuts_notes_1", 1); openRequest.onerror = function (e) console.log ("Errore durante l'apertura di db"); console .dir (e);; openRequest.onupgradeneeded = function (e) var thisDb = e.target.result; var objectStore; // Crea sistema operativo Nota if (! thisDb.objectStoreNames.contains ("note")) console .log ("Devo rendere nota l'archivio oggetti"); objectStore = thisDb.createObjectStore ("note", keyPath: "id", autoIncrement: true);; openRequest.onsuccess = function (e) db = e.target.result; db.onerror = function (event) // Gestore di errori generici per tutti gli errori indirizzati a // richieste del database! alert ("Errore del database:" + event.target.errorCode); console.dir (event.target);; displayNotes ();;

La nostra prima azione è controllare il supporto IndexedDB. Se il browser dell'utente non è compatibile, utilizziamo un avviso e interrompiamo la funzione. Probabilmente sarebbe meglio trasferirli in una pagina che spieghi pienamente perché non possono usare l'applicazione. (E per essere chiari, potremmo anche costruire un'applicazione che ha fatto uso di WebSQL come backup, ma ancora una volta - il mio focus qui è sulla semplicità.)

Dopo aver memorizzato nella cache alcuni selettori jQuery, che utilizzeremo in tutta l'app, apriremo quindi il nostro database IndexedDB. Il database è abbastanza semplice. Nel onupgradeneeded gestore si può vedere un negozio di oggetti chiamato gli appunti in fase di creazione. Una volta che tutto è fatto, il onSuccess il gestore eseguirà una chiamata a displayNotes.

Il displayNotes Funzione

 function displayNotes () var transaction = db.transaction (["note"], "readonly"); var content = ""; transaction.oncomplete = function (event) $ (" # noteList "). html (content);; var handleResult = function (event) var cursor = event.target.result; if (cursor) content + = ""; contenuto + =""; contenuto + =""; contenuto + =""; cursor.continue (); else content + ="
Titoloaggiornato 
"+ Cursor.value.title +""+ DtFormat (cursor.value.updated) +"Modifica Elimina
";; var objectStore = transaction.objectStore (" note "); objectStore.openCursor (). onsuccess = handleResult;

Il displayNotes la funzione fa quello che ti aspetti: ottieni tutti i dati e visualizzali. Abbiamo discusso su come ottenere tutte le righe di dati nella voce precedente, ma voglio sottolineare qualcosa di leggermente diverso in questo esempio. Si noti che abbiamo un nuovo gestore di eventi, onComplete, che abbiamo legato alla transazione stessa. In precedenza, abbiamo utilizzato gli eventi solo all'interno delle azioni, dentro la transazione, ma IndexedDB ci consente di farlo anche al livello più alto. Questo diventa particolarmente utile in un caso come questo. Abbiamo una stringa gigante, la nostra tabella HTML, che costruiamo su ogni iterazione dei nostri dati. Possiamo usare le transazioni onComplete gestore per avvolgere la porzione di display e scriverla usando una semplice chiamata jQuery.

Il Elimina, modificare, e Inserisci funzioni

 $ ("# noteList"). on ("click", "a.delete", function (e) var thisId = $ (this) .parent (). parent (). data ("chiave"); var t = db.transaction (["note"], "readwrite"); var request = t.objectStore ("note"). delete (thisId); t.oncomplete = function (event) displayNotes (); $ noteDetail.hide (); $ noteForm.hide ();; return false;); $ ("# noteList"). on ("click", "a.edit", function (e) var thisId = $ (this) .parent (). parent (). data ("chiave"); richiesta var = db.transaction (["note"], "readwrite") .objectStore ("note") .get (thisId); request.onsuccess = function (evento) var note = request.result; $ ("# chiave" ) .val (note.id); $ ("# title"). val (note.title); $ ("# body"). val (note.body); $ noteDetail.hide (); $ noteForm.show ();; return false;); $ ("# noteList"). on ("click", "td", function () var thisId = $ (this) .parent (). data ("chiave"); var transaction = db.transaction ([" nota "]); var objectStore = transaction.objectStore (" note "); var request = objectStore.get (thisId); request.onsuccess = function (event) var note = request.result; $ noteDetail.html ("

"+ Note.title +"

"+ Note.body +"

") .show (); $ noteForm.hide ();;); $ (" # addNoteButton "). on (" clic ", funzione (e) $ (" # titolo "). val (" " ) $ ("# body"). val (""); $ ("# chiave"). val (""); $ noteDetail.hide (); $ noteForm.show (););

I nostri prossimi due metodi (Elimina e modificare) è un altro esempio di questo stesso principio. Poiché nessuna delle chiamate IndexedDB è nuova, non ci preoccuperemo di esaminarle. La maggior parte della "carne" qui finisce per essere semplice manipolazione DOM per gestire le azioni particolari. Il gestore per fare clic sul pulsante Aggiungi è esattamente quello, quindi salveremo anche quello.

Il Salvare Funzione

 $ ("# saveNoteButton"). on ("click", function () var title = $ ("# title"). val (); var body = $ ("# body"). val (); chiave var = $ ("# chiave"). val (); var t = db.transaction (["note"], "readwrite"); if (chiave === "") t.objectStore ("note"). add (title: title, body: body, updated: new Date ()); else t.objectStore ("note") .put (title: title, body: body, updated: new Date (), id: Number (chiave)); t.oncomplete = function (event) $ ("# chiave"). val (""); $ ("# title"). val (""); $ (" #body "). val (" "); displayNotes (); $ noteForm.hide ();; return false;); );

Il prossimo bocconcino interessante è il salvare metodo. Deve usare un po 'di logica per determinare se stiamo aggiungendo o aggiornando, ma anche questo è piuttosto semplice. E questo è tutto! Un'applicazione IndexedDB completa, se semplice. Puoi giocare da solo con questa demo scaricando il codice sorgente allegato.


In conclusione

Questo è tutto per la seconda parte! Il terzo articolo prenderà questa applicazione e inizierà ad aggiungere funzionalità aggiuntive tra cui la ricerca e le proprietà basate su array.