Arbeider med IndexedDB

En av de mer interessante utviklingen i webstandarder i det siste er Indexed Database (IndexedDB for short) spesifikasjon. For en morsom tid kan du lese spesifikasjonen selv. I denne opplæringen vil jeg forklare denne funksjonen og forhåpentligvis gi deg litt inspirasjon til å bruke denne kraftige funksjonen selv.


Oversikt

Som en spesifikasjon, IndexedDB er for tiden en kandidat anbefaling.

I et nøtteskall gir IndexedDB en måte for deg å lagre store mengder data i brukerens nettleser. Ethvert program som trenger å sende mye data over ledningen, kan i stor grad dra nytte av å kunne lagre dataene på klienten i stedet. Selvfølgelig er lagring bare en del av ligningen. IndexedDB gir også en kraftig indeksert basert søkings API for å hente dataene du trenger.

Du lurer kanskje på hvordan IndexedDB skiller seg fra andre lagringsmekanismer?

Cookies er ekstremt godt støttet, men har juridiske implikasjoner og begrenset lagringsplass. Også - de sendes frem og tilbake til serveren med hver forespørsel, og helt negerer fordelene med klientsiden lagring.

Lokal lagring er også veldig godt støttet, men begrenset i forhold til den totale mengden lagring du kan bruke. Lokal lagring gir ikke et ekte "søk" API fordi data bare hentes via nøkkelverdier. Lokal lagring er utmerket for "bestemte" ting du kanskje vil lagre, for eksempel preferanser, mens IndexedDB er bedre egnet for Ad hoc-data (som en database).

Før vi går videre skjønt, la oss få en ærlig snakk om tilstanden IndexedDB når det gjelder nettleserstøtte. Som en spesifikasjon, IndexedDB er for tiden en kandidat anbefaling. På dette punktet er folkene bak spesifikasjonen fornøyd med det, men ser nå etter tilbakemelding fra utviklerfellesskapet. Spesifikasjonen kan endres mellom nå og siste trinn, W3C-anbefaling. Generelt sett gjør nettleserne som støtter IndexedDB alle på en ganske konsekvent måte, men utviklere bør være forberedt på å håndtere prefikser og legge merke til oppdateringer i fremtiden.

Som for de nettleserne som støtter IndexedDB, har du litt av et dilemma. Støtte er ganske bra for skrivebordet, men nesten ikke-eksisterende for mobil. La oss se hva utmerket nettstedet CanIUse.com sier:


Chrome for Android støtter funksjonen, men svært få personer bruker for øyeblikket nettleseren på Android-enheter. Mangel på mobil støtte betyr at du ikke bør bruke den? Selvfølgelig ikke! Forhåpentligvis er alle våre lesere kjent med begrepet progressiv forbedring. Funksjoner som IndexedDB kan legges til din søknad på en måte som ikke vil bryte i ikke-støttede nettlesere. Du kan bruke wrapper-biblioteker til å bytte til WebSQL på mobil, eller bare hoppe over lagring av data lokalt på mobilklienter. Personlig tror jeg at evnen til å cache store datamengder på klienten er viktig nok til å bruke nå selv uten mobil støtte.


La oss komme i gang

Vi har dekket spesifikasjonen og støtten, nå la oss se på bruk av funksjonen. Det aller første vi bør gjøre er å sjekke for IndexedDB-støtte. Selv om det finnes verktøy der ute som gir generiske måter å sjekke etter nettleserfunksjoner, kan vi gjøre dette mye enklere siden vi bare ser etter en bestemt ting.

document.addEventListener ("DOMContentLoaded", funksjon () if ("indexedDB" i vinduet) console.log ("JA! Jeg kan gjøre det! WOOT !!!"); else console.log ("Jeg har en trist.");, Falsk);

Kodestykket ovenfor (tilgjengelig i test1.html hvis du laster ned zip-filen som er vedlagt denne artikkelen) bruker du DOMContentLoaded arrangement for å vente på at siden lastes inn. (Ok, det er litt tydelig, men jeg skjønner at dette kanskje ikke er kjent for folk som bare har brukt jQuery.) Jeg ser da bare om indeksertDB finnes i vindu objekt og i så fall er det godt å gå. Det er det enkleste eksemplet, men vanligvis vil vi trolig ønske å lagre dette slik at vi senere vet om vi kan bruke funksjonen. Her er et litt mer avansert eksempel (test2.html).

var idbSupported = false; document.addEventListener ("DOMContentLoaded", funksjon () if ("indexedDB" i vinduet) idbSupported = true;, false);

Alt jeg har gjort er opprettet en global variabel, idbSupported, som kan brukes som flagg for å se om den nåværende nettleseren kan bruke IndexedDB.


Å åpne en database

IndexedDB, som du kan forestille deg, benytter databaser. For å være klar, er dette ikke en SQL Server-implementering. Denne databasen er lokal i nettleseren og kun tilgjengelig for brukeren. IndexedDB-databaser følger de samme reglene som informasjonskapsler og lokal lagring. En database er unik for domenet den ble lastet inn fra. Så for eksempel vil en database kalt "Foo" opprettet på foo.com ikke være i konflikt med en database med samme navn på goo.com. Ikke bare vil det ikke komme i konflikt, det vil ikke være tilgjengelig for andre domener også. Du kan lagre data for ditt nettsted og vite at et annet nettsted ikke vil kunne få tilgang til det.

Å åpne en database gjøres via den åpne kommandoen. I grunnleggende bruk oppgir du et navn og en versjon. Versjonen er veldig viktig av grunner vil jeg dekke mer senere. Her er et enkelt eksempel:

var openRequest = indeksertDB.open ("test", 1);

Å åpne en database er en asynkron operasjon. For å håndtere resultatet av denne operasjonen må du legge til noen hendelseslyttere. Det er fire forskjellige typer hendelser som kan avfyres:

  • suksess
  • feil
  • upgradeneeded
  • blokkert

Du kan sikkert gjette hvilken suksess og feil som innebærer. Den oppgraderte hendelsen brukes både når brukeren først åpner databasen, samt når du endrer versjonen. Blokkert er ikke noe som vil skje vanligvis, men kan brann hvis en tidligere tilkobling aldri ble stengt.

Vanligvis bør det skje at det ved første treff på nettstedet ditt vil oppgradere den aktuelle hendelsen. Etter det - bare suksesshåndtereren. La oss se på et enkelt eksempel (test3.html).

var idbSupported = false; var db; document.addEventListener ("DOMContentLoaded", funksjon () if ("indexedDB" i vinduet) idbSupported = true; hvis (idbSupported) var openRequest = indeksertDB.open ("test", 1); openRequest.onupgradeneeded = function (e) console.log ("Oppgradering ..."); openRequest.onsuccess = funksjon (e) console.log ("Suksess!"); db = e.target.result; openRequest.onerror = funksjon ) console.log ("Error"); console.dir (e);, falskt);

Igjen sjekker vi for å se om IndexedDB faktisk støttes, og hvis det er, åpner vi en database. Vi har dekket tre hendelser her - oppgraderingen nødvendig hendelsen, suksesshendelsen og feilhendelsen. For nå fokus på suksess hendelsen. Arrangementet er bestått en handler via target.result. Vi har kopiert det til en global variabel som heter db. Dette er noe vi vil bruke senere til å faktisk legge til data. Hvis du kjører dette i nettleseren din (i en som støtter IndexedDB selvfølgelig!), Bør du se oppgraderingen og suksessmeldingen i konsollen din første gang du kjører skriptet. Den andre, og så videre, ganger du kjører skriptet, bør du bare se suksessmeldingen.


Objektbutikker

Så langt har vi sjekket for IndexedDB-støtte, bekreftet det, og åpnet en forbindelse til en database. Nå trenger vi et sted å lagre data. IndexedDB har et konsept av "Objektbutikker". Du kan tenke på dette som en typisk databasetabell. (Det er mye mer løs enn en typisk database tabell, men bekymre deg ikke om det nå.) Objektbutikker har data (åpenbart), men også et tastatur og et valgfritt sett med indekser. Keypaths er i utgangspunktet unike identifikatorer for dine data og kommer i noen forskjellige formater. Indeksene vil bli dekket senere når vi begynner å snakke om å hente data.

Nå for noe viktig. Husk den oppgraderte hendelsen nevnt før? Du kan bare opprette objektforretninger under en oppgraderingshendelse. Nå - som standard - dette kjøres automatisk første gang en bruker treffer nettstedet ditt. Du kan bruke dette til å lage objektobutikker. Det avgjørende å huske er at hvis du noen gang trenger det modifisere Objektet ditt lagrer, du må oppgradere versjonen (tilbake i den åpne hendelsen) og skrive kode for å håndtere endringene dine. La oss se på et enkelt eksempel på dette i aksjon.

var idbSupported = false; var db; document.addEventListener ("DOMContentLoaded", funksjon () if ("indexedDB" i vinduet) idbSupported = true; hvis (idbSupported) var openRequest = indeksertDB.open ("test_v2", 1); openRequest.onupgradeneeded = function (e) console.log ("running onupgradeneeded"); var thisDB = e.target.result; hvis (! thisDB.objectStoreNames.contains ("firstOS")) thisDB.createObjectStore ("firstOS"); openRequest .onsuccess = funksjon (e) console.log ("Suksess!"); db = e.target.result; openRequest.onerror = funksjon (e) console.log ("Error"); console.dir );   ,falsk);

Dette eksempelet (test4.html) bygger på de forrige oppføringene, så jeg vil bare fokusere på det som er nytt. I den oppgraderte hendelsen har jeg benyttet databasevariabelen som er sendt til den (thisDB). En av egenskapene til denne variabelen er en liste over eksisterende objektforretninger som heter objectStoreNames. For folkens nysgjerrige, dette er ikke et enkelt utvalg, men en "DOMStringList." Ikke spør meg - men det går du. Vi kan bruke inneholder Metode for å se om vareobjektet eksisterer, og hvis ikke, opprett det. Dette er en av de få synkroniserte funksjonene i IndexedDB, slik at vi ikke trenger å lytte til resultatet.

For å oppsummere da - dette er hva som ville skje når en bruker besøker nettstedet ditt. Første gang de er her, brenner den oppgraderte hendelsen. Koden kontrollerer for å se om en objektbutikk, "firstOS" eksisterer. Det vil ikke. Derfor er det opprettet. Deretter løper suksessbehandleren. Den andre gangen de besøker nettstedet, vil versionsnummeret være det samme, slik at den oppgraderte hendelsen er ikke sparken.

Forestill deg at du ønsket å legge til en annen objektbutikk. Alt du trenger å gjøre er å øke versjonsnummeret og i utgangspunktet duplisere innholdet / createObjectStore-kodeblokken du ser ovenfor. Den kule tingen er at din oppgraderte kode vil støtte både folk som er splitter nye til nettstedet, samt de som allerede hadde det første objektet butikken. Her er et eksempel på dette (test5.html):

var openRequest = indeksertDB.open ("test_v2", 2); openRequest.onupgradeneeded = function (e) console.log ("kjører onupgradeneeded"); var detteDB = e.target.result; hvis (! thisDB.objectStoreNames.contains ("firstOS")) thisDB.createObjectStore ("firstOS");  hvis (! thisDB.objectStoreNames.contains ("secondOS")) thisDB.createObjectStore ("secondOS"); 

Legge til data

Når du har lagret objektobjektene dine, kan du begynne å legge til data. Dette er - kanskje - en av de kuleste aspektene av IndexedDB. I motsetning til tradisjonelle tabellbaserte databaser, lar IndexedDB deg lagre et objekt som det er. Hva det betyr er at du kan ta et generisk JavaScript-objekt og bare lagre det. Ferdig. Det er åpenbart at det er noen advarsler her, men for det meste er det det.

Arbeide med data krever at du bruker en transaksjon. Transaksjoner tar to argumenter. Den første er en rekke bord du skal jobbe med. Mesteparten av tiden vil dette være ett bord. Det andre argumentet er typen transaksjon. Det er to typer transaksjoner: readonly og readwrite. Legge til data vil være en readwrite-operasjon. La oss begynne med å opprette transaksjonen:

// Anta db er en databasevariabel åpnet tidligere var transaction = db.transaction (["people"], "readwrite");

Merk objektet butikken, "folk", er bare en vi har gjort opp i eksemplet ovenfor. Vår neste fulle demo vil gjøre bruk av den. Etter å ha fått transaksjonen, spør du om det for objektet butikken du sa at du ville jobbe med:

var butikk = transaction.objectStore ("people");

Nå som du har butikken, kan du legge til data. Dette gjøres via - vent på det - Legg til metode.

// Definer en person var person = navn: navn, e-post: email, opprettet: ny dato () // Utfør add var request = store.add (person, 1);

Husk tidligere, vi sa at du kan lagre data du vil ha (for det meste). Så mitt personobjekt ovenfor er helt vilkårlig. Jeg kunne ha brukt fornavn og etternavn i stedet for bare å gi navn. Jeg kunne ha brukt en kjønnsegenskap. Du får ideen. Det andre argumentet er nøkkelen som brukes til å identifisere dataene entydig. I dette tilfellet har vi hardt kodet det til 1 som kommer til å forårsake et problem ganske raskt. Det er ok - vi lærer å rette opp det.

Add-operasjonen er ascynkron, slik at vi kan legge til to hendelseshåndterere for resultatet.

request.onerror = funksjon (e) console.log ("Feil", e.target.error.name); // noen type feilhåndterer request.onsuccess = funksjon (e) console.log ("Woot! Did it"); 

Vi har en onerror Handler for feil og onsuccess for gode endringer. Ganske åpenbart, men la oss se et komplett eksempel. Du finner dette i filen test6.html.

>
      

Eksemplet ovenfor inneholder et lite skjema med en knapp for å avbrå en hendelse for å lagre dataene i IndexedDB. Kjør dette i nettleseren din, legg til noe i skjemafeltene, og klikk på Legg til. Hvis du har nettleserens dev-verktøy åpne, bør du se noe slikt.


Dette er et flott tidspunkt å påpeke at Chrome har en utmerket seer for IndexedDB-data. Hvis du klikker på fanen Ressurser, utvider du indeksen IndexedDB, du kan se databasen som er opprettet av denne demoen, så vel som objektet bare er skrevet inn.


For sjansen av det, gå videre og klikk på Legg til Data-knappen igjen. Du bør se en feil i konsollen:


Feilmeldingen skal være en anelse. ConstraintError betyr at vi bare prøvde å legge til data med samme nøkkel som en som allerede eksisterte. Hvis du husker, har vi hardt kodet den nøkkelen og vi visste det skulle bli et problem. Det er på tide å snakke nøkler.


Keys

Taster er IndexedDBs versjon av primærnøkler. Tradisjonelle databaser kan ha tabeller uten nøkler, men hver objektbutikk må ha en nøkkel. IndexedDB tillater et par forskjellige typer nøkler.

Det første alternativet er å bare spesifisere det selv, som vi gjorde over. Vi kunne bruke logikk for å generere unike nøkler.

Ditt andre alternativ er et tastatur, hvor nøkkelen er basert på en egenskap av dataene selv. Tenk på vårt folks eksempel - vi kunne bruke en e-postadresse som en nøkkel.

Det tredje alternativet, og etter min mening, det enkleste, er å bruke en nøkkelgenerator. Dette fungerer mye som en autonummer primærnøkkel og er den enkleste metoden for å angi nøkler.

Nøkler defineres når objektforretninger opprettes. Her er to eksempler - en som bruker en nøkkelbane og en en generator.

thisDb.createObjectStore ("test", keyPath: "email"); thisDb.createObjectStore ("test2", autoIncrement: true);

Vi kan endre vår tidligere demo ved å opprette en objektbutikk med en autoIncrement-nøkkel:

thisDB.createObjectStore ("folk", autoIncrement: true);

Til slutt kan vi ta Add-samtalen vi brukte før, og fjern den hardkodede nøkkelen:

var request = store.add (person);

Det er det! Nå kan du legge til data hele dagen lang. Du kan finne denne versjonen i test7.html.


Lese data

La oss nå bytte til å lese individuelle datastykker (vi vil dekke å lese større sett med data senere). Igjen, dette vil bli gjort i en transaksjon og vil være asynkron. Her er et enkelt eksempel:

var transaction = db.transaction (["test"], "readonly"); var objectStore = transaction.objectStore ("test"); // x er noen verdi var ob = objectStore.get (x); ob.onsuccess = funksjon (e) 

Vær oppmerksom på at transaksjonen er skrivebeskyttet. API-anropet er bare et enkelt få anrop med nøkkelen sendt inn. Som en rask side, hvis du tror å bruke IndexedDB, er det litt ordentlig, merk at du også kan koble mange av disse anropene. Her er nøyaktig samme kode skrevet mye strammere:

db.transaction (["test"], "readonly"). objektStore ("test"). få (X) .onsuccess = funksjon (e) 

Personlig finner jeg fortsatt IndexedDB litt komplisert, så jeg foretrekker den "ødelagte" tilnærmingen for å hjelpe meg å holde rede på hva som skjer.

Resultatet av get's onsuccess handler er objektet du lagret før. Når du har det objektet, kan du gjøre hva du vil. I vår neste demonstrasjon (test8.html) Vi har lagt til et enkelt skjemafelt for å la deg taste inn en nøkkel og skrive ut resultatet. Her er et eksempel:


Handler for Get Data-knappen er under:

funksjon getPerson (e) var nøkkel = document.querySelector ("# key"). verdi; hvis (nøkkel === "" || erNaN (nøkkel)) tilbake; var transaction = db.transaction (["people"], "readonly"); var butikk = transaction.objectStore ("people"); var request = store.get (tall (nøkkel)); request.onsuccess = funksjon (e) var result = e.target.result; console.dir (resultat); hvis (resultat) var s = "

Nøkkel "+ nøkkel +"

"; for (var felt i resultat) s + = field +" = "+ result [field] +"
"; document.querySelector (" # status "). innerHTML = s; else document.querySelector (" # status "). innerHTML ="

Ingen treff

";

For det meste bør dette være selvforklarende. Få verdien fra feltet og kjør et få anrop på objektbutikken hentet fra en transaksjon. Legg merke til at skjermkoden ganske enkelt blir alle feltene og dumper dem ut. I en reell applikasjon vil du (forhåpentligvis) vite hva dine data inneholder og jobbe med bestemte felt.


Leser flere data

Så det var slik at du skulle få et dataopptak. Hva med a mye av data? IndexedDB har støtte for det som kalles en markør. En markør lar deg iterere over data. Du kan lage markører med et valgfritt område (et grunnfilter) og en retning.

Som et eksempel åpner følgende kodeblokk en markør for å hente all data fra en objektbutikk. Som alt annet vi har gjort med data, er dette asynkron og i en transaksjon.

var transaction = db.transaction (["test"], "readonly"); var objectStore = transaction.objectStore ("test"); var markør = objectStore.openCursor (); cursor.onsuccess = funksjon (e) var res = e.target.result; hvis (res) console.log ("Key", res.key); console.dir ("Data", res.value); res.continue (); 

Suksesshandleren er bestått av et resultatobjekt (variabelen er over). Den inneholder nøkkelen, objektet for dataene (i verdienstasten ovenfor) og en fortsettelsesmetode som brukes til å iterere til neste datatykke.

I den følgende funksjonen har vi brukt en markør til å iterere over alle objektstore dataene. Siden vi jobber med "person" data har vi kalt denne getPeople:

funksjon getPeople (e) var s = ""; db.transaction (["people"], "readonly"). objektStore ("people"). openCursor (). onsuccess = funksjon (e) var markør = e.target.result; hvis (markør) s + = "

Nøkkel "+ cursor.key +"

"; for (var-feltet i cursor.value) s + = field +" = "+ cursor.value [field] +"
"; s + ="

"; cursor.continue (); document.querySelector (" # status2 "). innerHTML = s;

Du kan se en fullstendig demonstrasjon av dette i nedlastingen som fil test9.html. Den har en Add Person-logikk som i de tidligere eksemplene, så bare opprett et par personer, og trykk deretter på knappen for å vise alle dataene.


Så nå vet du hvordan du får et data, så vel som hvordan du får alle dataene. La oss nå slå vårt siste emne - arbeide med indekser.


De kaller dette IndexedDB, Høyre?

Vi har snakket om IndexedDB for hele artikkelen, men har ennå ikke gjort noen - godt indekser. Indekser er en avgjørende del av IndexedDB-objektbutikker. De gir en måte å hente data basert på deres verdi, samt angi om en verdi skal være unik i en butikk. Senere viser vi hvordan du bruker indekser for å få en rekke data.

Først - hvordan lager du en indeks? Som alt annet strukturelt, må de gjøres i en oppgraderingshendelse, i utgangspunktet samtidig lager du objektbutikken din. Her er et eksempel:

var objectStore = thisDb.createObjectStore ("folk", autoIncrement: true); // første arg er navnet på indeksen, andre er banen (col); objectStore.createIndex ("navn", "navn", unikt: false); objectStore.createIndex ("email", "email", unique: true);

I første linje lager vi butikken. Vi tar det resultatet (et objektStore objekt) og kjører createIndex metode. Det første argumentet er navnet på indeksen, og det andre er eiendommen som vil bli indeksert. I de fleste tilfeller tror jeg at du vil bruke samme navn for begge. Det endelige argumentet er et sett med alternativer. For nå bruker vi bare en, unik. Den første indeksen for navn er ikke unik. Den andre for e-post er. Når vi lagrer data, vil IndexedDB sjekke disse indeksene og sørge for at e-postegenskapen er unik. Det vil også gjøre litt datahåndtering på baksiden for å sikre at vi kan hente data av disse indeksene.

Hvordan virker det? Når du henter en objektbutikk via en transaksjon, kan du deretter be om en indeks fra den butikken. Bruk koden ovenfor, her er et eksempel på det:

var transaction = db.transaction (["people"], "readonly"); var butikk = transaction.objectStore ("people"); var index = store.index ("navn"); // navn er noen verdi var request = index.get (navn);

Først får vi transaksjonen, etterfulgt av butikken, og deretter indekser. Som vi har sagt før, kan du koble de første tre linjene for å gjøre det litt mer kompakt hvis du vil.

Når du har en indeks, kan du da utføre en ring på det for å hente data etter navn. Vi kunne gjøre noe lignende for e-post også. Resultatet av denne anrop er enda en asynkron objekt du kan binde en onsuccess handler til. Her er et eksempel på at handleren finnes i filen test10.html:

request.onsuccess = funksjon (e) var result = e.target.result; hvis (resultat) var s = "

Navn "+ navn +"

"; for (var felt i resultat) s + = field +" = "+ result [field] +"
"; document.querySelector (" # status "). innerHTML = s; else document.querySelector (" # status "). innerHTML ="

Ingen treff

";

Legg merke til at en indeks anrop kan returnere flere objekter. Siden navnet vårt ikke er unikt, bør vi sannsynligvis endre koden for å håndtere det, men det er ikke nødvendig.

La oss nå kaste det opp et hakk. Du har sett ved hjelp av få API på indeksen for å få en verdi basert på den egenskapen. Hva om du vil få et bredere sett med data? Det siste begrepet vi skal lære i dag er Ranges. Ranger er en måte å velge et delsett av en indeks på. For eksempel, gitt en indeks på en navnegenskap, kan vi bruke et utvalg for å finne navn som begynner med A opp til navn som begynner med C. Ranges kommer i noen forskjellige varianter. De kan være "alt under noen markører", "alt over noen markører", og "noe mellom en lavere markør og en høyere markør." Til slutt, for å gjøre ting interessant, kan områdene være inkluderende eller eksklusive. I utgangspunktet betyr det for et område som går fra A-C, kan vi spesifisere om vi vil inkludere A og C i området eller bare verdiene mellom dem. Til slutt kan du også be om både stigende og nedadgående rekkevidde.

Rangene er opprettet ved hjelp av et toplevel-objekt som heter IDBKeyRange. Den har tre metoder av interesse: lowerbound, øvre grense, og bundet. lowerbound brukes til å lage et område som starter med en lavere verdi og returnerer alle dataene "over" den. øvre grense er motsatt. Og endelig - bundet brukes til å støtte et sett med data med både en nedre og øvre grense. La oss se på noen eksempler:

// Verdier over 39 var oldRange = IDBKeyRange.lowerBound (39); // Verdier 40a dn over var oldRange2 = IDBKeyRange.lowerBound (40, true); // 39 og mindre ... var youngRange = IDBKeyRange.upperBound (40); // 39 og mindre ... var youngRange2 = IDBKeyRange.upperBound (39, true); // ikke ung eller gammel ... du kan også spesifisere inkluderende / eksklusiv var okRange = IDBKeyRange.bound (20,40)

Når du har en rekkevidde, kan du sende den til en indeksens openCursor-metode. Dette gir deg en iterator som slår over verdiene som samsvarer med dette området. Som en praktisk måte er dette egentlig ikke et søk i seg selv. Du kan bruke dette til å søke innhold basert på begynnelsen på en streng, men ikke midten eller slutten. La oss se på et fullstendig eksempel. Først skal vi opprette en enkel skjema for å søke etter personer:

Starter med: 
Slutter med:

Vi skal tillate søk som består av noen av de tre typene av områder (igjen, en verdi og høyere, en høyeste verdi, eller verdiene i to innganger). La oss nå se på hendelseshandleren for dette skjemaet.

funksjon getPeople (e) var name = document.querySelector ("# nameSearch"). verdi; var endnavn = document.querySelector ("# nameSearchEnd"). verdi; hvis (navn == "" && etternavn == "") returnere; var transaction = db.transaction (["people"], "readonly"); var butikk = transaction.objectStore ("people"); var index = store.index ("navn"); // Gjør rekkevidden avhengig av hvilken type vi gjør var rekkevidde; hvis (navn! = "" && etternavn! = "") range = IDBKeyRange.bound (navn, etternavn);  annet hvis (navn == "") range = IDBKeyRange.upperBound (etternavn);  ellers range = IDBKeyRange.lowerBound (navn);  var s = ""; index.openCursor (rekkevidde) .onsuccess = funksjon (e) var markør = e.target.result; hvis (markør) s + = "

Nøkkel "+ cursor.key +"

"; for (var-feltet i cursor.value) s + = field +" = "+ cursor.value [field] +"
"; s + ="

"; cursor.continue (); document.querySelector (" # status "). innerHTML = s;

Fra topp til bunn begynner vi å ta tak i de to formfeltene. Deretter oppretter vi en transaksjon, og fra det får vi butikken og indeksen. Nå for den semi-komplekse delen. Siden vi har tre forskjellige typer områder vi trenger å støtte, må vi gjøre litt betinget logikk for å finne ut hva vi trenger. Hvilket område vi lager, er basert på hvilke felt du fyller inn. Hva er fint er at når vi har rekkevidden, sender vi det bare til indeksen og åpner markøren. Det er det! Du finner dette fulle eksempelet i test11.html. Sørg for å skrive inn noen verdier først, slik at du har data for å søke.


Hva blir det neste?

Tro det eller ikke - vi har bare begynt vår diskusjon om IndexedDB. I neste artikkel dekker vi flere emner, inkludert oppdateringer og slett, arraybaserte verdier og noen generelle tips for å jobbe med IndexedDB.