HTML5本地存储IndexedDB基础使用
做项目时需要用H5本地存储,感觉还不错 下面是一些基础知识和一个完整的实例
HTML5 的一个重要特性是本地数据持久性,它使用户能够在线和离线访问 Web 应用程序。此外,本地数据持久性使移动应用程序更灵敏,使用的带宽更少,而且能够在低带宽场景中更高效地工作。HTML5 提供了一些本地数据持久性选项。第一个选项是 localstorage
,它支持您使用一个简单的键值对来存储数据。IndexedDB(一个更加强大的选项)支持您本地存储大量对象,并使用健壮的数据访问机制检索数据。
IndexedDB API 取代了 Web Storage API,后者在 HTML5 规范中已不推荐使用。(但一些领先的浏览器仍然支持 Web Storage,其中包括苹果公司的 Safari 和 Opera Web 浏览器)与 Web Storage 相比,IndexedDB 具有多个优势,其中包括索引、事务处理和健壮的查询功能。本文将通过一系列的示例来展示如何管理 IndexedDB 数据库。
重要概念
一个网站可能有一个或多个 IndexedDB 数据库,每个数据库必须具有惟一的名称。
一个数据库可包含一个或多个对象存储。一个对象存储(由一个名称惟一标识)是一个记录集合。每个记录有一个键 和一个值。该值是一个对象,可拥有一个或多个属性。键可能基于某个键生成器,从一个键路径衍生出来,或者是显式设置。一个键生成器自动生成惟一的连续正整数。键路径定义了键值的路径。它可以是单个 JavaScript 标识符或多个由句点分隔的标识符。
规范中包含一个异步 API 和一个同步 API。同步 API 用于 Web 浏览器中。异步 API 使用请求和回调。
在以下示例中,输出附加到一个具有 ID result
的 div
标记上。要更新 result
元素,可在每个数据操作期间清除并设置 innerHTML
属性。每个示例 JavaScript 函数由 HTML 按钮的一个 onclick
事件调用。
object store
有了数据库后我们自然希望创建一个表用来存储数据,但indexedDB中没有表的概念,而是objectStore,一个数据库中可以包含多个objectStore,objectStore是一个灵活的数据结构,可以存放多种类型数据。也就是说一个objectStore相当于一张表,里面存储的每条数据和一个键相关联。
我们可以使用每条记录中的某个指定字段作为键值(keyPath),也可以使用自动生成的递增数字作为键值(keyGenerator),也可以不指定。选择键的类型不同,objectStore可以存储的数据结构也有差异
事务
在对新数据库做任何事情之前,需要开始一个事务。事务中需要指定该事务跨越哪些object store。
事务具有三种模式
- 只读:read,不能修改数据库数据,可以并发执行
- 读写:readwrite,可以进行读写操作
- 版本变更:verionchange
当用户访问你的网站时,如果用户的浏览器支持IndexedDB,则首先触发的是upgradeneeded事件
完整示例
<!doctype html> <html> <head> </head> <body> <script> var db; //检测浏览器是否支持 indexedDBOk function indexedDBOk() { return "indexedDB" in window; } document.addEventListener("DOMContentLoaded", function() { //判断 indexedDBOk 支持 是/否? if(!indexedDBOk) return; //打开数据库 这个变量其中一个属性是一个已存在的对象存储list,名为objectStoreNames var openRequest = indexedDB.open("idarticle_people6",1); openRequest.onupgradeneeded = function(e) { var thisDB = e.target.result; //通过contains方法检车某个对象是否已经存在了,如果不存在则可进行创建 if(!thisDB.objectStoreNames.contains("people")) { //使用key生成器 var os = thisDB.createObjectStore("people", {autoIncrement:true}); //索引 //os.createIndex(索引名称,列,指定某个列是否是唯一) os.createIndex("name", "name", {unique:false}); //I want email to be unique os.createIndex("email", "email", {unique:true}); } } openRequest.onsuccess = function(e) { db = e.target.result; //监听添加事件 document.querySelector("#addButton").addEventListener("click", addPerson, false); document.querySelector("#getButton").addEventListener("click", getPeople, false); document.querySelector("#delete").addEventListener("click", deleteData, false); document.querySelector("#getStore").addEventListener("click", getDataByKey, false); document.querySelector("#getButton1").addEventListener("click", getDataByKey1, false); document.querySelector("#getButton2").addEventListener("click", getDataByKey2, false); } openRequest.onerror = function(e) { //Do something for the error } },false); function addPerson(e) { var name = document.querySelector("#name").value; var email = document.querySelector("#email").value; console.log("About to add "+name+"/"+email); // 对象 = db.事物(将要处理的数组,事物类型) var transaction = db.transaction(["people"],"readwrite"); //设置存储对象people为为读写操作,然后使用objectStore指定要操作的存储对象,存在变量store var store = transaction.objectStore("people"); //设置添加数据 var person = { name:name, email:email, created:new Date() } //声明一个普通的javascript对象,使用store的add方法 增加这个对象到对象存储中 var request = store.add(person); //增加数据是异步操作,增加两个事件监听 request.onerror = function(e) { alert("Sorry, that email address already exists."); console.log("Error",e.target.error.name); console.dir(e.target); //some type of error handler } request.onsuccess = function(e) { console.log("Woot! Did it"); } } function getPeople(e) { var name = document.querySelector("#nameSearch").value; var endname = document.querySelector("#nameSearchEnd").value; if(name == "" && endname == "") return; // 对象 = db.事物(将要处理的数组,事物类型) var transaction = db.transaction(["people"],"readonly"); //设置存储对象people为为读写操作,然后使用objectStore指定要操作的存储对象,存在变量store var store = transaction.objectStore("people"); var index = store.index("name"); //Make the range depending on what type we are doing var range; if(name != "" && endname != "") { range = IDBKeyRange.bound(name, endname); } else if(name == "") { range = IDBKeyRange.upperBound(endname); } else { range = IDBKeyRange.lowerBound(name); } var s = ""; index.openCursor(range).onsuccess = function(e) { var cursor = e.target.result; if(cursor) { s += "<h2>Key "+cursor.key+"</h2><p>"; for(var field in cursor.value) { s+= field+"="+cursor.value[field]+"<br/>"; } s+="</p>"; cursor.continue(); } document.querySelector("#status").innerHTML = s; } } //清空store function deleteData(e) { var transaction = db.transaction(["people"],"readwrite"); var store=transaction.objectStore("people"); store.clear(); } //列表查询 function getDataByKey(e) { var s = ""; db.transaction(["people"], "readonly").objectStore("people").openCursor().onsuccess = function(e) { var cursor = e.target.result; if(cursor) { s += "<h2>Key "+cursor.key+"</h2><p>"; for(var field in cursor.value) { s+= field+"="+cursor.value[field]+"<br/>"; } s+="</p>"; cursor.continue(); } document.querySelector("#status2").innerHTML = s; } } //查询 function getDataByKey1(){ var name = document.querySelector("#nameSearch1").value; if(name === "" ) return; var transaction = db.transaction(["people"],"readonly"); var store = transaction.objectStore("people"); var index = store.index("name"); var request = index.get(name); request.onsuccess=function(e){ var result = e.target.result; console.log(result.email); }; } //更新 function getDataByKey2(e){ var name = document.querySelector("#nameSearch2").value; if(name === "" ) return; var transaction = db.transaction(["people"],"readwrite"); var store=transaction.objectStore("people"); var index = store.index("name"); var request=index.get(name); request.onsuccess=function(e){ var result = e.target.result; result.email=909; store.put(result); }; } </script> <input type="text" id="name" placeholder="Name"><br/> <input type="email" id="email" placeholder="Email"><br/> <button id="addButton">Add Data</button> <p/> Starting with: <input type="text" id="nameSearch" placeholder="Name"><br/> Ending with: <input type="text" id="nameSearchEnd" placeholder="Name"><br/> <button id="getButton">Get By Name Range</button> <p/> <p> <button id="delete">delete clear</button> </p> <p> <button id="getStore">查找数据(列)</button> </p> <p id="status2"> </p> <p/> <input type="text" id="nameSearch1" placeholder="Name"><br/> <button id="getButton1">查找数据</button> <p/> <p/> <input type="text" id="nameSearch2" placeholder="Name"><br/> <button id="getButton2">更新数据</button> <p/> <div id="status"></div> </body> </html>