localStorage/sessionStorage的优点前端
localStorage/sessionStorage的局限web
IndexedDB 特色sql
IndexedDB vs Web Storage
Web Storage使用简单字符串键值对在本地存储数据,方便灵活,可是对于大量结构化数据存储力不从心,IndexedDB是为了可以在客户端存储大量的结构化数据,而且使用索引高效检索的API。
IndexedDB的技术特色是,不须要你去写特定的sql语句来对数据进行操做,它是nosql的,数据形式使用的是json。数据库
IndexedDB里数据以对象的形式存储,每一个对象都有一个key值索引。IndexedDB里的操做都是事务性的。一种对象存储在一个objectStore里,objectStore就至关于关系数据库里的表。IndexedDB能够有不少objectStore,objectStore里能够有不少对象。每一个对象能够用key值获取。
IndexedDB vs LocalStoragejson
IndexedDB和LocalStorage都是用来在浏览器里存储数据,但它们使用不一样的技术,有不一样的用途,你须要根据本身的状况适当的选择使用哪一种。LocalStorage是用key-value键值模式存储数据,但跟IndexedDB不同的是,它的数据并非按对象形式存储。它存储的数据都是字符串形式。若是你想让LocalStorage存储对象,你须要借助JSON.stringify()能将对象变成字符串形式,再用JSON.parse()将字符串还原成对象。但若是要存储大量的复杂的数据,这并非一种很好的方案。毕竟,localstorage就是专门为小数量数据设计的,它的api是同步的。api
IndexedDB很适合存储大量数据,它的API是异步调用的。IndexedDB使用索引存储数据,各类数据库操做放在事务中执行。IndexedDB甚至还支持简单的数据类型。IndexedDB比localstorage强大得多,但它的API也相对复杂。数组
对于简单的数据,你应该继续使用localstorage,但当你但愿存储大量数据时,IndexedDB会明显的更适合,IndexedDB能提供你更为复杂的查询数据的方式。浏览器
IndexedDB vs Web SQL
WebSQL也是一种在浏览器里存储数据的技术,跟IndexedDB不一样的是,IndexedDB更像是一个NoSQL数据库,而WebSQL更像是关系型数据库,使用SQL查询数据。W3C已经再也不支持这种技术。
由于再也不支持,因此你就不要在项目中使用这种技术了。cookie
IndexedDB vs Cookies
Cookies,每次HTTP接受和发送都会传递Cookies数据,它会占用额外的流量。例如,若是你有一个10KB的Cookies数据,发送10次请求,那么,总计就会有100KB的数据在网络上传输。Cookies只能是字符串。浏览器里存储Cookies的空间有限,不少用户禁止浏览器使用Cookies。因此,Cookies只能用来存储小量的非关键的数据。网络
(1)setItem(key,value):添加本地存储数据。两个参数,很是简单就不说了。 (2)getItem(key):经过key获取相应的Value。 (3)removeItem(key):经过key删除本地数据。 (4)clear():清空数据。
建立、打开数据库
须要根据不一样浏览器的内核,建立indexedDB对象
var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB
打开一个数据库,open方法, 该方法接收两个参数:
var name = 'person-text', version = 1, db var request = indexedDB.open(name, version) request.onsuccess = function(event) { db = event.target.result; db.onsuccess = function(event) { console.log('数据库操做成功!') }; db.onerror = function(event) { console.error('数据库操做发生错误!', event.target.errorCode) }; console.log('打开数据库成功!') } request.onerror = function(event) { console.error('建立数据库出错') console.error('error code:', event.target.errorCode) } request.onupgradeneeded = function(event) { // 更新对象存储空间和索引 .... }
如果本域下不存在名为 person-text 的数据库,则上述代码会建立一个名为person-text、版本号为1的数据库; 触发的事件依次为: upgradeneeded、 success.
如果已存在名为person-text的数据库, 则上述代码会打开该数据库; 只触发success/error事件,不会触发upgradeneeded事件. db是对该数据库的引用.
建立对象存储空间和索引
在key-value型数据库(如indexedDB)中, 一个数据库会有多个对象存储空间,每一个存储空间有本身的主键、索引等;
建立对象存储空间的操做通常放在建立数据库成功回调里:
request.onupgradeneeded = function(event) { // 更新对象存储空间和索引 .... var database = event.target.result var objectStore = database.createObjectStore("person", { keyPath: "id" }) objectStore.createIndex('name', 'name', { unique: true }) objectStore.createIndex('age', 'age', { unique: false }) }
onupgradeneeded 是咱们惟一能够修改数据库结构的地方。在这里面,咱们能够建立和删除对象存储空间以及构建和删除索引。
在数据库对象database上,有如下方法可供调用:
数据操做(增删改查)
对数据库的操做(增删查改等)都须要经过事务来完成,事务具备三种模式:
数据库对象的transaction()方法接收两个参数:
var transaction = db.transaction(['person'], 'readwrite') transaction.oncomplete = function(event) { console.log('事务完成!') } transaction.onerror = function(event) { console.log('事务失败!', event.target.errorCode) } transaction.onabort = function(event) { console.log('事务回滚!') }
向数据库中增长数据
经过事务对象transaction,在objectStore()方法中指定对象存储空间,就获得了能够对该对象存储空间进行操做的对象objectStore.
向数据库中增长数据,add()方法增长的对象,如果数据库中已存在相同的主键,或者惟一性索引的键值重复,则该条数据不会插入进去
var objectStore = transaction.objectStore('person') // 指定对象存储空间 var data = [{"name": "张三", "age": "21", "sex": "男", "id": "11" }, {"name": "李四", "age": "19", "sex": "男", "id": "12" }, {"name": "王五", "age": "21", "sex": "女", "id": "13"}, {"name": "赵六", "age": "24", "sex": "男", "id": "14"}] data.forEach(function(item, index){ var request = objectStore.add(item) request.onsuccess = function(event) { console.log('插入成功!', index) console.log(event.target.result, item.id); // add()方法调用成功后result是被添加的值的键(id) } })
修改数据库中的数据
var objectStore = transaction.objectStore('person') objectStore.put({"name": "李四", "age": "22", "sex": "男", "id": "12" })
该方法与add()不一样之处在于,数据库中若存在相同主键或者惟一性索引重复,则会更新该条数据,不然插入新数据。
从数据库中删除数据
var objectStore = transaction.objectStore('person') var request = objectStore.delete('12'); // 经过键id来删除 request.onsuccess = function(event) { console.log('删除成功!'); }
从数据中获取数据
var objectStore = transaction.objectStore('person') var request = objectStore.get('13') request.onsuccess = function(event) { console.log('获取成功!', event) }
使用索引
在前面,咱们建立了两个索引name和age, 配置对象里面的unique属性标志该值是否惟一
如今咱们想找到name属性值为'张三'的对象,就可使用索引。
var objectStore = db.transaction('person').objectStore('person') // 打开对象存储空间 var index = objectStore.index('name') // 使用索引 var request = index.get('张三') // 建立一个查找数据的请求 request.onsuccess = function(event) { console.log('The result is:', event.target.result) }
使用游标
使用一次索引,咱们只能获得一条数据; 若是咱们须要获得全部数据,或某一类数据,可使用游标.
获得一个能够操做游标的请求对象有两个方法:
// 匹配值为Bill的数据 var lowerBoundKeyRange = IDBKeyRange.only("Bill") // 匹配全部在 "Bill" 前面的, 包括 "Bill" var lowerBoundKeyRange = IDBKeyRange.lowerBound("Bill"); // 匹配全部在 “Bill” 前面的, 可是不须要包括 "Bill" var lowerBoundOpenKeyRange = IDBKeyRange.lowerBound("Bill", true); // 匹配全部在'Donna'后面的, 可是不包括"Donna" var upperBoundOpenKeyRange = IDBKeyRange.upperBound("Donna", true); // 匹配全部在"Bill" 和 "Donna" 之间的, 可是不包括 "Donna" var boundKeyRange = IDBKeyRange.bound("Bill", "Donna", false, true);
游标默认遍历方向是按主键从小到大,有时候咱们倒序遍历,此时能够给openCursor()
方法传递第二个参数: direction: next|nextunique|prev|prevunique
游标的使用有如下几处:
var list = []; var index = db.transaction('person').objectStore('person') index.openCursor().onsuccess = function(event) { var cursor = event.target.result if (cursor) { console.log('cursor.value:', cursor.value); list.push(cursor.value) cursor.continue() } else { console.log('list:', list) } }
var list = [] var index = db.transaction('person').objectStore('person').index('age') index.openCursor('24').onsuccess = function(event) { var cursor = event.target.result if (cursor) { console.log('cursor.value:', cursor.value); list.push(cursor.value) cursor.continue() } else { console.log('list:', list) } }
使用游标时,须要在成功回调里拿到result对象,判断是否取完了数据:若数据已取完,result是undefined; 若未取完,则result是个IDBCursorWithValue对象,需调用continue()方法继续取数据。 也能够根据本身需求, 对数据进行过滤。
在索引age上使用openCursor()方法时,若不传参数,则会遍历全部数据
关闭和删除数据库
关闭数据库只须要在数据库对象db上调用close()方法便可 db.close()
关闭数据库后,db对象仍然保存着该数据库的相关信息,只是没法再开启事务
删除数据库则须要使用indexedDB.deleteDatabase(dbName)
方法