Een van de interessantere ontwikkelingen in webstandaarden van de laatste tijd is de Indexed Database (afgekort IndexedDB) specificatie. Voor een leuke tijd kun je de specificatie zelf lezen. In deze tutorial zal ik deze functie uitleggen en hopelijk inspiratie bieden om deze krachtige functie zelf te gebruiken.
Als een specificatie is IndexedDB momenteel een Kandidaat-Aanbeveling.
In een notendop biedt IndexedDB een manier voor u om grote hoeveelheden gegevens op te slaan in de browser van uw gebruiker. Elke toepassing die veel gegevens via de draad moet verzenden, kan veel baat hebben bij het kunnen opslaan van die gegevens op de client. Natuurlijk is opslag slechts een deel van de vergelijking. IndexedDB biedt ook een krachtige geïndexeerde opzoek-API om de gegevens op te halen die u nodig hebt.
U vraagt zich misschien af hoe IndexedDB verschilt van andere opslagmechanismen?
Cookies worden buitengewoon goed ondersteund, maar hebben juridische implicaties en beperkte opslagruimte. Ook worden ze bij elk verzoek heen en weer verzonden naar de server, waardoor de voordelen van opslag aan de clientzijde volledig teniet worden gedaan.
Lokale opslag wordt ook zeer goed ondersteund, maar beperkt in termen van de totale hoeveelheid opslag die u kunt gebruiken. Lokale opslag biedt geen echte "zoek" -APA, omdat gegevens alleen via sleutelwaarden worden opgehaald. Lokale opslag is geweldig voor "specifieke" dingen die u misschien wilt opslaan, bijvoorbeeld voorkeuren, terwijl IndexedDB beter geschikt is voor Ad Hoc-gegevens (net als een database).
Maar voordat we verder gaan, laten we eerlijk praten over de status van IndexedDB in termen van browserondersteuning. Als een specificatie is IndexedDB momenteel een Kandidaat-Aanbeveling. Op dit punt zijn de mensen achter de specificatie er blij mee, maar zijn nu op zoek naar feedback van de ontwikkelaarsgemeenschap. De specificatie kan veranderen tussen nu en de laatste fase, W3C-aanbeveling. Over het algemeen doen de browsers die IndexedDB ondersteunen nu allemaal op een redelijk consistente manier, maar ontwikkelaars moeten voorbereid zijn om met voorvoegsels om te gaan en in de toekomst kennis te nemen van updates.
Wat betreft die browsers die IndexedDB ondersteunen, je hebt een beetje een dilemma. Ondersteuning is behoorlijk goed voor de desktop, maar vrijwel onbestaande voor mobiel. Laten we eens kijken wat de uitstekend site CanIUse.com zegt:
Chrome voor Android ondersteunt deze functie, maar slechts enkele mensen gebruiken die browser momenteel op Android-apparaten. Betekent het ontbreken van mobiele ondersteuning dat je het niet zou moeten gebruiken? Natuurlijk niet! Hopelijk zijn al onze lezers bekend met het concept van progressieve verbetering. Functies zoals IndexedDB kunnen aan uw applicatie worden toegevoegd op een manier die niet zal breken in niet-ondersteunde browsers. U zou wrapper-bibliotheken kunnen gebruiken om over te schakelen naar WebSQL op mobiele apparaten of om eenvoudig gegevens lokaal op te slaan op uw mobiele clients. Persoonlijk ben ik van mening dat de mogelijkheid om grote blokken gegevens op de client te cachen belangrijk genoeg is om nu te gebruiken, zelfs zonder mobiele ondersteuning.
We hebben de specificaties en ondersteuning behandeld, laten we nu kijken naar het gebruik van de functie. Het allereerste dat we moeten doen, is controleren op ondersteuning van IndexedDB. Hoewel er hulpprogramma's beschikbaar zijn die generieke manieren bieden om te controleren op browserfuncties, kunnen we dit veel eenvoudiger maken omdat we slechts naar één specifiek item zoeken.
document.addEventListener ("DOMContentLoaded", function () if ("indexedDB" in venster) console.log ("YES !!! I CAN DO IT !!! WOOT !!!"; else console.log ("I has a sad.");, False);
Het codefragment hierboven (beschikbaar in test1.html
als u het zip-bestand downloadt dat bij dit artikel is gevoegd) gebruikt het DOMContentLoaded
gebeurtenis om te wachten tot de pagina is geladen. (Ok, dat is een beetje voor de hand liggend, maar ik weet dat dit misschien niet bekend is voor mensen die alleen jQuery hebben gebruikt.) Ik zie dan eenvoudig of geïndexeerdDB bestaat in de venster
object en zo ja, we zijn goed om te gaan. Dat is het eenvoudigste voorbeeld, maar meestal willen we dit waarschijnlijk opslaan, zodat we later weten of we de functie kunnen gebruiken. Hier is een iets meer geavanceerd voorbeeld (test2.html
).
var idbSupported = false; document.addEventListener ("DOMContentLoaded", function () if ("indexedDB" in venster) idbSupported = true;, false);
Alles wat ik heb gedaan is een globale variabele gemaakt, idbSupported
, die kan worden gebruikt als een vlag om te zien of de huidige browser IndexedDB kan gebruiken.
IndexedDB maakt, zoals u zich kunt voorstellen, gebruik van databases. Voor de duidelijkheid, dit is geen SQL Server-implementatie. Deze database is lokaal voor de browser en alleen beschikbaar voor de gebruiker. IndexedDB-databases volgen dezelfde regels als cookies en lokale opslag. Een database is uniek voor het domein waaruit het is geladen. Een database met de naam "Foo" gemaakt op foo.com zal dus niet conflicteren met een database met dezelfde naam op goo.com. Niet alleen zal het niet conflicteren, het zal ook niet beschikbaar zijn voor andere domeinen. U kunt gegevens voor uw website opslaan met de wetenschap dat een andere website er geen toegang toe heeft.
Het openen van een database gebeurt via de opdracht open. In basisgebruik geeft u een naam en een versie op. De versie is heel belangrijk om redenen die ik later zal bespreken. Hier is een eenvoudig voorbeeld:
var openRequest = geïndexeerdDB.open ("test", 1);
Het openen van een database is een asynchrone bewerking. Om het resultaat van deze bewerking af te handelen, moet u enkele gebeurtenislisteners toevoegen. Er zijn vier verschillende soorten evenementen die kunnen worden geactiveerd:
U kunt waarschijnlijk raden wat succes en fouten betekenen. De upgrade-gebeurtenis wordt zowel gebruikt wanneer de gebruiker de database voor het eerst opent als wanneer u de versie wijzigt. Geblokkeerd is niet iets dat meestal zal gebeuren, maar kan ontbranden als een eerdere verbinding nooit werd gesloten.
Wat er meestal zou moeten gebeuren, is dat bij de eerste treffer op uw site de gebeurtenis met de nieuwe upgrade wordt geactiveerd. Daarna - alleen de succeshandler. Laten we een eenvoudig voorbeeld bekijken (test3.html
).
var idbSupported = false; var db; document.addEventListener ("DOMContentLoaded", function () if ("indexedDB" in venster) idbSupported = true; if (idbSupported) var openRequest = indexedDB.open ("test", 1); openRequest.onupgradeneeded = function (e) console.log ("Upgrading ..."); openRequest.onsuccess = function (e) console.log ("Succes!"); db = e.target.result; openRequest.onerror = function (e ) console.log ("Fout"); console.dir (e);, false);
We controleren nogmaals of IndexedDB daadwerkelijk wordt ondersteund en als dit het geval is, openen we een database. We hebben hier drie evenementen besproken: het evenement voor upgrade nodig, het succesevenement en de foutgebeurtenis. Voor nu richten op het succes evenement. Het evenement wordt doorgegeven via een handler target.result
. We hebben dat gekopieerd naar een globale variabele genaamd db
. Dit is iets dat we later zullen gebruiken om daadwerkelijk gegevens toe te voegen. Als u dit in uw browser uitvoert (in een browser die uiteraard IndexedDB ondersteunt!), Zou u het upgrade- en succesbericht in uw console moeten zien wanneer u het script voor het eerst uitvoert. De tweede, enzovoort, keer dat u het script uitvoert, moet u alleen het succesbericht zien.
Tot nu toe hebben we gecontroleerd op ondersteuning van IndexedDB, dit bevestigd en een verbinding met een database geopend. Nu hebben we een plaats nodig om gegevens op te slaan. IndexedDB heeft een concept van 'Object Stores'. Je kunt dit zien als een typische databasetabel. (Het is veel meer los dan een typische databasetabel, maar maak je daar nu geen zorgen over.) Object-stores hebben data (uiteraard) maar ook een keypath en een optionele set indexen. Keypaths zijn in principe unieke ID's voor uw gegevens en zijn er in een paar verschillende indelingen. Indexen worden later behandeld wanneer we beginnen met praten over het ophalen van gegevens.
Nu voor iets cruciaals. Denk aan de eerder genoemde upgrade-gebeurtenis? U kunt alleen objectarchieven maken tijdens een evenement met nieuwe upgrades. Nu - standaard - wordt dit automatisch uitgevoerd wanneer een gebruiker voor de eerste keer op uw site komt. U kunt dit gebruiken om uw objectwinkels te maken. Het cruciale om te onthouden is dat als dat ooit nodig is wijzigen in je objectwinkels, moet je de versie upgraden (terug in die open gebeurtenis) en code schrijven om je wijzigingen af te handelen. Laten we eens kijken naar een eenvoudig voorbeeld hiervan in actie.
var idbSupported = false; var db; document.addEventListener ("DOMContentLoaded", function () if ("indexedDB" in venster) idbSupported = true; if (idbSupported) var openRequest = indexedDB.open ("test_v2", 1); openRequest.onupgradeneeded = function (e) console.log ("running ongradeneeded"); var thisDB = e.target.result; if (! thisDB.objectStoreNames.contains ("firstOS")) thisDB.createObjectStore ("firstOS"); openRequest .onsuccess = functie (e) console.log ("Succes!"); db = e.target.result; openRequest.onerror = function (e) console.log ("Error"); console.dir (e );, false);
Dit voorbeeld (test4.html
) bouwt voort op de eerdere inzendingen, dus ik zal me alleen concentreren op wat er nieuw is. Binnen de geüpgradede gebeurtenis heb ik gebruik gemaakt van de databasevariabele die eraan is doorgegeven (thisDB
). Een van de eigenschappen van deze variabele is een lijst met bestaande objectarchieven die worden aangeroepen objectStoreNames
. Voor nieuwsgierigen is dit geen eenvoudige array, maar een 'DOMStringList'. Vraag het mij niet - maar daar ga je. We kunnen de gebruiken bevat
methode om te zien of onze object store bestaat, en zo niet, maak deze dan aan. Dit is een van de weinige synchrone functies in IndexedDB, dus we hoeven niet naar het resultaat te luisteren.
Samenvattend: dit is wat er zou gebeuren wanneer een gebruiker uw site bezoekt. De eerste keer dat ze hier zijn, wordt het evenement met de upgrade geactiveerd. De code controleert of een objectarchief "firstOS" bestaat. Het zal niet. Daarom - het is gemaakt. Vervolgens wordt de succeshandler uitgevoerd. De tweede keer dat ze de site bezoeken, is het versienummer hetzelfde, dus de upgrade-gebeurtenis is niet ontslagen.
Stel je nu voor dat je een tweede objectwinkel wilde toevoegen. Het enige dat u hoeft te doen, is het versienummer verhogen en in feite dupliceren van het codeblok contains / createObjectStore dat u hierboven ziet. Het leuke is dat uw geüpgradede code zowel mensen ondersteunt die nieuw zijn op de site als degenen die al de eerste objectwinkel hadden. Hier is een voorbeeld van (test5.html
):
var openRequest = geïndexeerdDB.open ("test_v2", 2); openRequest.onupgradeneeded = function (e) console.log ("running ongradeneeded"); var thisDB = e.target.result; if (! thisDB.objectStoreNames.contains ("firstOS")) thisDB.createObjectStore ("firstOS"); if (! thisDB.objectStoreNames.contains ("secondOS")) thisDB.createObjectStore ("secondOS");
Zodra u uw objectwinkels gereed hebt, kunt u beginnen met het toevoegen van gegevens. Dit is - misschien - een van de coolste aspecten van IndexedDB. In tegenstelling tot traditionele tabelgebaseerde databases, kunt u met IndexedDB een object opslaan zoals het is. Wat dat betekent is dat je een generiek JavaScript-object kunt nemen en het gewoon kunt opslaan. Gedaan. Uiteraard zijn hier een aantal kanttekeningen, maar meestal is dat het dan.
Werken met gegevens vereist dat u een transactie gebruikt. Transacties nemen twee argumenten. De eerste is een reeks tabellen waarmee u zult werken. Meestal zal dit een tafel zijn. Het tweede argument is het type transactie. Er zijn twee soorten transacties: readonly en readwrite. Het toevoegen van gegevens zal een readwrite-bewerking zijn. Laten we beginnen met het maken van de transactie:
// Stel dat db een databasevariabele is die eerder is geopend var transaction = db.transaction (["people"], "readwrite");
Let op het objectarchief, "mensen", is er slechts één die we in het bovenstaande voorbeeld hebben verzonnen. Onze volgende volledige demo zal er gebruik van maken. Na het ophalen van de transactie, vraagt u het vervolgens naar de objectwinkel waarmee u zei dat u zou werken:
var store = transaction.objectStore ("people");
Nu je de winkel hebt, kun je gegevens toevoegen. Dit gebeurt via de - wacht erop - toevoegen
methode.
// Definieer een persoon var persoon = naam: naam, e-mail: email, aangemaakt: nieuw Datum () // Voer de add var request = store.add (persoon, 1);
Onthoud eerder dat we hebben gezegd dat je alle gegevens die je wilt (voor het grootste deel) kunt opslaan. Dus mijn persoon die hiertegen bezwaar heeft is volkomen willekeurig. Ik had firstName en lastName kunnen gebruiken in plaats van alleen maar naam. Ik had een gendereigenschap kunnen gebruiken. Je snapt het idee. Het tweede argument is de sleutel die wordt gebruikt om de gegevens uniek te identificeren. In dit geval hebben we het hard gecodeerd in 1, wat een probleem vrij snel gaat veroorzaken. Dat is goed - we zullen leren hoe dit te corrigeren.
De toevoegbewerking is ascynchroon, dus we kunnen twee gebeurtenishandlers toevoegen voor het resultaat.
request.onerror = function (e) console.log ("Fout", e.target.error.name); // een of ander type foutverwerker request.onsuccess = function (e) console.log ("Woot! Did it");
We hebben een onerror
handler voor fouten en onsuccess
voor goede veranderingen. Vrij duidelijk, maar laten we een volledig voorbeeld bekijken. Je vindt dit in het bestand test6.html
.
Het bovenstaande voorbeeld bevat een klein formulier met een knop om een gebeurtenis af te vuren om de gegevens op te slaan in IndexedDB. Voer dit in uw browser uit, voeg iets toe aan de formuliervelden en klik op Toevoegen. Als u gereedschappen voor uw browser dev hebt geopend, ziet u zoiets als dit.
Dit is een goed moment om erop te wijzen dat Chrome een uitstekende viewer heeft voor IndexedDB-gegevens. Als u op het tabblad Bronnen klikt, vouwt u het gedeelte Geïndexeerde database uit. U kunt de door deze demo gemaakte database en het zojuist ingevoerde object bekijken.
Voor de zekerheid, ga je gang en druk op die knop Gegevens toevoegen opnieuw. Er zou een fout moeten verschijnen in de console:
De foutmelding moet een aanwijzing zijn. ConstraintError betekent dat we zojuist geprobeerd hebben gegevens toe te voegen met dezelfde sleutel als een sleutel die al bestond. Als je het onthoudt, hebben we die sleutel hard gecodeerd en wij wist dat zou een probleem zijn. Het is tijd om te praten.
Sleutels zijn de geïndexeerde versie van primaire sleutels van DB. Traditionele databases kunnen tabellen bevatten zonder sleutels, maar elke objectwinkel moet een sleutel hebben. GeïndexeerdDB staat een paar verschillende soorten sleutels toe.
De eerste optie is om het eenvoudig zelf te specificeren, zoals we hierboven deden. We kunnen logica gebruiken om unieke sleutels te genereren.
Uw tweede optie is een keypath, waarbij de sleutel is gebaseerd op een eigenschap van de gegevens zelf. Beschouw het voorbeeld van onze mensen - we zouden een e-mailadres als sleutel kunnen gebruiken.
Uw derde optie, en naar mijn mening de eenvoudigste, is het gebruik van een sleutelgenerator. Dit werkt net als een primaire sleutel van een autonumber en is de eenvoudigste manier om sleutels te specificeren.
Sleutels worden gedefinieerd wanneer objectwinkels worden gemaakt. Hier zijn twee voorbeelden - een met een sleutelpad en een met een generator.
thisDb.createObjectStore ("test", keyPath: "email"); thisDb.createObjectStore ("test2", autoIncrement: true);
We kunnen onze vorige demo aanpassen door een objectwinkel te maken met een autoIncrement-sleutel:
thisDB.createObjectStore ("people", autoIncrement: true);
Ten slotte kunnen we de oproep gebruiken die we eerder hebben gebruikt en de hardcodesleutel verwijderen:
var request = store.add (persoon);
Dat is het! Nu kunt u de hele dag gegevens toevoegen. U kunt deze versie vinden in test7.html
.
Laten we nu overschakelen naar het lezen van individuele gegevens (we zullen later grotere sets gegevens gaan lezen). Nogmaals, dit gebeurt in een transactie en is asynchroon. Hier is een eenvoudig voorbeeld:
var transaction = db.transaction (["test"], "readonly"); var objectStore = transaction.objectStore ("test"); // x is een of andere waarde var ob = objectStore.get (x); ob.onsuccess = functie (e)
Merk op dat de transactie alleen-lezen is. De API-aanroep is slechts een eenvoudige oproep met de sleutel doorgegeven. Even terzijde, als u denkt dat het gebruik van IndexedDB een beetje uitgebreid is, kunt u ook veel van die aanroepen koppelen. Hier is precies dezelfde code geschreven veel strakker:
db.transaction (["test"], "readonly"). objectStore ("test"). get (X) .onsuccess = functie (e)
Persoonlijk vind ik IndexedDB nog steeds een beetje ingewikkeld, dus ik geef de voorkeur aan de 'uitgebroken' benadering om me te helpen bijhouden wat er aan de hand is.
Het resultaat van de onsucces-handler van get's is het object dat u eerder hebt opgeslagen. Zodra je dat object hebt, kun je doen wat je wilt. In onze volgende demo (test8.html
) hebben we een eenvoudig formulierveld toegevoegd waarmee u een sleutel kunt invoeren en het resultaat kunt afdrukken. Hier is een voorbeeld:
De handler voor de knop Gegevens ophalen bevindt zich hieronder:
functie getPerson (e) var key = document.querySelector ("# key"). waarde; als (key === "" || isNaN (key)) return; var transaction = db.transaction (["people"], "readonly"); var store = transaction.objectStore ("people"); var request = store.get (Number (key)); request.onsuccess = function (e) var result = e.target.result; console.dir (resultaat); if (resultaat) var s = "Sleutel "+ toets +"
"; voor (var-veld in resultaat) s + = veld +" = "+ resultaat [veld] +"
"; document.querySelector (" # status "). innerHTML = s; else document.querySelector (" # status "). innerHTML ="Geen match
";
Voor het grootste deel moet dit voor zichzelf spreken. Haal de waarde uit het veld en voer een get call uit op het objectarchief dat is verkregen uit een transactie. Merk op dat de displaycode eenvoudig wordt allemaal de velden en dumpt ze. In een echte applicatie zou u (hopelijk) weten wat uw gegevens bevatten en met specifieke velden werken.
Dus dat is hoe je een stuk gegevens zou krijgen. Wat denk je van lot Van de gegevens? IndexedDB heeft ondersteuning voor wat een cursor wordt genoemd. Met een cursor kunt u gegevens herhalen. U kunt cursors maken met een optioneel bereik (een basisfilter) en een richting.
Als voorbeeld opent het volgende codeblok een cursor om alle gegevens van een objectarchief op te halen. Zoals alles wat we met gegevens hebben gedaan, is dit asynchroon en in een transactie.
var transaction = db.transaction (["test"], "readonly"); var objectStore = transaction.objectStore ("test"); var cursor = objectStore.openCursor (); cursor.onsuccess = functie (e) var res = e.target.result; if (res) console.log ("Key", res.key); console.dir ("Data", res.value); res.continue ();
De succeshandler krijgt een resultaatobject doorgegeven (de variabele res hierboven). Het bevat de sleutel, het object voor de gegevens (in de waardetoets hierboven) en een continue methode die wordt gebruikt om naar het volgende stuk gegevens te itereren.
In de volgende functie hebben we een cursor gebruikt om alle objectwinkelgegevens te herhalen. Omdat we werken met 'persoons'-gegevens, hebben we dit getPeople genoemd:
function getPeople (e) var s = ""; db.transaction (["people"], "readonly"). objectStore ("people"). openCursor (). onsuccess = functie (e) var cursor = e.target.result; if (cursor) s + = "Sleutel "+ cursor.key +"
"; voor (var veld in cursor.value) s + = veld +" = "+ cursor.value [veld] +"
"; cursor.continue (); document.querySelector (" # status2 "). innerHTMLHTML = s;
"; s + ="
Je kunt een volledige demo hiervan zien in je download als bestand test9.html
. Het heeft een Add Person-logica zoals in de eerdere voorbeelden, dus maak eenvoudig een paar mensen en druk op de knop om alle gegevens weer te geven.
Dus nu weet u hoe u één stuk gegevens kunt krijgen en hoe u alle gegevens kunt ophalen. Laten we nu ons laatste onderwerp raken - werken met indexen.
We hebben het gehad over IndexedDB voor het hele artikel, maar hebben nog geen echte indexen gemaakt. Indexen vormen een cruciaal onderdeel van objectde winkels van IndexedDB. Ze bieden een manier om gegevens op te halen op basis van hun waarde en om aan te geven of een waarde uniek moet zijn in een winkel. Later zullen we laten zien hoe u indexen kunt gebruiken om een reeks gegevens te krijgen.
Ten eerste - hoe creëer je een index? Zoals alles structureel, moeten ze worden gedaan in een upgrade-evenement, in feite op hetzelfde moment dat u uw objectwinkel maakt. Hier is een voorbeeld:
var objectStore = thisDb.createObjectStore ("people", autoIncrement: true); // eerste arg is de naam van de index, de tweede is het pad (col); objectStore.createIndex ("name", "name", unique: false); objectStore.createIndex ("email", "email", unique: true);
In de eerste regel maken we de winkel. We nemen dat resultaat (een Object Object object) en voeren het createIndex
methode. Het eerste argument is de naam voor de index en de tweede is de eigenschap die wordt geïndexeerd. In de meeste gevallen denk ik dat je dezelfde naam voor beide zult gebruiken. Het laatste argument is een reeks opties. Voor nu gebruiken we er slechts één, uniek. De eerste index voor naam is niet uniek. De tweede voor e-mail is. Wanneer we gegevens opslaan, zal IndexedDB deze indexen controleren en ervoor zorgen dat de eigenschap e-mail uniek is. Het zal ook wat gegevensverwerking aan de achterkant uitvoeren om ervoor te zorgen dat we gegevens kunnen ophalen met deze indexen.
Hoe werkt dat? Zodra u een objectarchief via een transactie hebt opgehaald, kunt u vervolgens een index van die winkel opvragen. Met behulp van de bovenstaande code, hier is een voorbeeld van:
var transaction = db.transaction (["people"], "readonly"); var store = transaction.objectStore ("people"); var index = store.index ("naam"); // naam is een enkele waarde var request = index.get (naam);
Eerst krijgen we de transactie, gevolgd door de winkel en vervolgens de index. Zoals we al eerder hebben gezegd, kun je die eerste drie regels koppelen om het een beetje compacter te maken als je dat wilt.
Als u eenmaal een index heeft, kunt u vervolgens een krijgen
roep het op om gegevens op naam op te halen. We kunnen ook iets soortgelijks voor e-mail doen. Het resultaat van die aanroep is nog een ander asynchroon object waaraan u een inkomende succeshandler kunt binden. Hier is een voorbeeld van die handler gevonden in het bestand test10.html
:
request.onsuccess = function (e) var result = e.target.result; if (resultaat) var s = "Naam "+ naam +"
"; voor (var-veld in resultaat) s + = veld +" = "+ resultaat [veld] +"
"; document.querySelector (" # status "). innerHTML = s; else document.querySelector (" # status "). innerHTML ="Geen match
";
Merk op dat een index krijgen
oproep kan meerdere objecten retourneren. Aangezien onze naam niet uniek is, moeten we waarschijnlijk de code aanpassen om daarmee om te gaan, maar dit is niet verplicht.
Laten we nu een tandje bijsteken. U heeft de API get get gebruikt in de index om een waarde op basis van die eigenschap te krijgen. Wat als u een bredere set gegevens wilt hebben? De laatste termijn die we vandaag gaan leren zijn Ranges. Bereiken zijn een manier om een subset van een index te selecteren. Als u bijvoorbeeld een index op een naameigenschap opgeeft, kunnen we een bereik gebruiken om namen te vinden die beginnen met A tot namen die beginnen met C. Er zijn verschillende bereiken. Ze kunnen "alles onder een of andere markering", "alles boven een of andere markering" en "iets tussen een lagere markering en een hogere markering" zijn. Tot slot, alleen om het interessant te maken, kunnen reeksen inclusief of exclusief zijn. In feite betekent dit dat voor een bereik van A-C, we kunnen specificeren of we A en C in het bereik willen opnemen of alleen de waarden daartussen. Ten slotte kunt u ook zowel oplopende als aflopende reeksen aanvragen.
Bereiken worden gemaakt met behulp van een object op het hoogste niveau met de naam IDBKeyRange. Het heeft drie interessante methoden: onderGrens
, bovenGrens
, en gebonden
. onderGrens
wordt gebruikt om een bereik te maken dat begint bij een lagere waarde en alle gegevens "erboven" retourneert. bovenGrens
is het tegenovergestelde. En tenslotte - gebonden
wordt gebruikt om een reeks gegevens te ondersteunen met zowel een onder- als een bovengrens. Laten we enkele voorbeelden bekijken:
// Waarden over 39 var oldRange = IDBKeyRange.lowerBound (39); // Waarden 40a dn over var oldRange2 = IDBKeyRange.lowerBound (40, true); // 39 en kleiner ... var youngRange = IDBKeyRange.upperBound (40); // 39 en kleiner ... var youngRange2 = IDBKeyRange.upperBound (39, true); // niet jong of oud ... u kunt ook inclusive / exclusive opgeven var okRange = IDBKeyRange.bound (20,40)
Zodra u een bereik hebt, kunt u dit doorgeven aan de openCursor-methode van een index. Dit geeft u een iterator om de waarden die bij dat bereik horen te omzeilen. Praktisch gezien is dit niet echt een zoekopdracht op zich. U kunt dit gebruiken om inhoud te zoeken op basis van het begin van een tekenreeks, maar niet in het midden of einde. Laten we naar een volledig voorbeeld kijken. Eerst maken we een eenvoudig formulier om mensen te zoeken:
Beginnend met:
Eindigend met:
We gaan zoekopdrachten toestaan die uit een van de drie typen bereiken bestaan (opnieuw een waarde en hoger, een hoogste waarde of de waarden binnen twee ingangen). Laten we nu kijken naar de gebeurtenishandler voor dit formulier.
functie getPeople (e) var name = document.querySelector ("# nameSearch"). value; var endname = document.querySelector ("# nameSearchEnd"). value; als (naam == "" && endname == "") terugkomt; var transaction = db.transaction (["people"], "readonly"); var store = transaction.objectStore ("people"); var index = store.index ("naam"); // Maak het bereik afhankelijk van het type dat we aan het doen zijn var-bereik; if (name! = "" && endname! = "") range = IDBKeyRange.bound (naam, eindnaam); else if (name == "") range = IDBKeyRange.upperBound (endname); else range = IDBKeyRange.lowerBound (naam); var s = ""; index.openCursor (bereik) .onsuccess = functie (e) var cursor = e.target.result; if (cursor) s + = "Sleutel "+ cursor.key +"
"; voor (var veld in cursor.value) s + = veld +" = "+ cursor.value [veld] +"
"; cursor.continue (); document.querySelector (" # status "). innerHTML = s;
"; s + ="
Van boven naar beneden - we beginnen met het grijpen van de twee formuliervelden. Vervolgens maken we een transactie en krijgen we de winkel en de index. Nu voor het semi-complexe gedeelte. Aangezien we drie verschillende soorten bereiken hebben, moeten we ondersteunen. We moeten een beetje voorwaardelijke logica doen om erachter te komen wat we nodig hebben. Welk bereik we maken, is gebaseerd op de velden die u invult. Wat leuk is, is dat zodra we het bereik hebben, we het eenvoudig doorgeven aan de index en de cursor openen. Dat is het! Je vindt dit volledige voorbeeld in test11.html
. Zorg ervoor dat u eerst enkele waarden invoert, zodat u gegevens kunt doorzoeken.
Geloof het of niet - we zijn pas begonnen aan onze discussie over IndexedDB. In het volgende artikel bespreken we aanvullende onderwerpen, waaronder updates en verwijderingen, op arsenet gebaseerde waarden en enkele algemene tips voor het werken met IndexedDB.