前端存储之indexedDB
在前一个阶段的工作中,项目组要开发一个平台,为了做出更好的用户体验,实现快速、高质量的交互,从而更快得到用户的反馈,要求在前端把数据存储起来,之后我去研究了下现在比较流行的前端存储数据库,找到了indexedDB,于是便对indexedDB做了一个较为深入的探索,此文就是记录探索过程的一些心得体会。
indexedDB为何物
在使用一个技术之前,先搞清楚它是什么,这对你的理解很重要,从DB就可以看出,它肯定是一个数据库,而说到数据库,有两种不同类型的数据库,就是关系型数据库和非关系型数据库,关系型数据库如Mysql、Oracle等将数据存储在表中,而非关系型数据库如Redis、MongoDB等将数据集作为个体对象存储。indexedDB就是一个非关系型数据库,它不需要你去写一些特定的sql语句来对数据库进行操作,因为它是nosql的,数据形式使用的是json,
indexedDB出现的意义
也许熟悉前端存储的会说,不是有了LocalStorage和Cookies吗?为什么还要推出indexedDB呢?其实对于在浏览器里存储数据,你可以使用cookies或local storage,但它们都是比较简单的技术,而IndexedDB提供了类似数据库风格的数据存储和使用方式。
首先说说Cookies,英文直接翻译过来就是小甜点,听起来很好吃,实际上并不是,每次HTTP接受和发送都会传递Cookies数据,它会占用额外的流量。例如,如果你有一个10KB的Cookies数据,发送10次请求,那么,总计就会有100KB的数据在网络上传输。Cookies只能是字符串。浏览器里存储Cookies的空间有限,很多用户禁止浏览器使用Cookies。所以,Cookies只能用来存储小量的非关键的数据。
其次说说LocalStorage,LocalStorage是用key-value键值模式存储数据,但跟IndexedDB不一样的是,它的数据并不是按对象形式存储。它存储的数据都是字符串形式。如果你想让LocalStorage存储对象,你需要借助JSON.stringify()能将对象变成字符串形式,再用JSON.parse()将字符串还原成对象。但如果要存储大量的复杂的数据,这并不是一种很好的方案。毕竟,localstorage就是专门为小数量数据设计的,所以它的api设计为同步的。而IndexedDB很适合存储大量数据,它的API是异步调用的。IndexedDB使用索引存储数据,各种数据库操作放在事务中执行。IndexedDB甚至还支持简单的数据类型。IndexedDB比localstorage强大得多,但它的API也相对复杂。对于简单的数据,你应该继续使用localstorage,但当你希望存储大量数据时,IndexedDB会明显的更适合,IndexedDB能提供你更为复杂的查询数据的方式。
indexedDB的特性
1.对象仓库
有了数据库后我们自然希望创建一个表用来存储数据,但indexedDB中没有表的概念,而是objectStore,一个数据库中可以包含多个objectStore,objectStore是一个灵活的数据结构,可以存放多种类型数据。也就是说一个objectStore相当于一张表,里面存储的每条数据和一个键相关联。我们可以使用每条记录中的某个指定字段作为键值(keyPath),也可以使用自动生成的递增数字作为键值(keyGenerator),也可以不指定。选择键的类型不同,objectStore可以存储的数据结构也有差异。
|
键类型 |
存储数据 |
|
不使用 |
任意值,但是没添加一条数据的时候需要指定键参数 |
|
keyPath |
任意值,但是没添加一条数据的时候需要指定键参数 |
|
keyGenerator |
任意值 |
|
都使用 |
Javascript对象,如果对象中有keyPath指定的属性则不生成新的键值,如果没有自动生成递增键值,填充keyPath指定属性 |

如上图,有一个用于保存person的object Store,这个仓库的键就是person的ID值。
2. 事务性
在indexedDB中,每一个对数据库操作是在一个事务的上下文中执行的。事务范围一次影响一个或多个object stores,你通过传入一个object store名字的数组到创建事务范围的函数来定义。例如:db.transaction(storeName, 'readwrite'),创建事务的第二个参数是事务模式。当请求一个事务时,必须决定是按照只读还是读写模式请求访问。
3. 基于请求
对indexedDB数据库的每次操作,描述为通过一个请求打开数据库,访问一个object store,再继续。IndexedDB API天生是基于请求的,这也是API异步本性指示。对于你在数据库执行的每次操作,你必须首先为这个操作创建一个请求。当请求完成,你可以响应由请求结果产生的事件和错误。
4. 异步
在IndexedDB大部分操作并不是我们常用的调用方法,返回结果的模式,而是请求—响应的模式,所谓异步API是指并不是这条指令执行完毕,我们就可以使用request.result来获取indexedDB对象了,就像使用ajax一样,语句执行完并不代表已经获取到了对象,所以我们一般在其回调函数中处理。
indexedDB怎么玩
IndexedDB 鼓励使用的基本模式如下所示:
- 打开数据库并且开始一个事务。
- 创建一个 object store。
- 构建一个请求来执行一些数据库操作,像增加或提取数据等。
- 通过监听正确类型的 DOM 事件以等待操作完成。
- 在操作结果上进行一些操作(可以在 request 对象中找到)
接下来如果想要理解indexedDB具体怎么玩,最好的方法就是创建一个简单的web应用:把人的姓名、电话、地址存储在IndexedDB里。IndexedDB里提供了简单的增、删、改、查接口,界面如下:

1.打开数据库
a) 首先,你需要知道你的浏览器是否支持IndexedDB。
var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;
if(!indexedDB)
{
console.log("你的浏览器不支持IndexedDB");
}
b) 创建请求打开indexedDB:一旦你的浏览器支持IndexedDB,我们就可以打开它。你不能直接打开IndexedDB数据库。IndexedDB需要你创建一个请求来打开它。
var request = indexedDB.open(name, version);
第一个参数是数据库的名称,第二个参数是数据库的版本号。版本号可以在升级数据库时用来调整数据库结构和数据。但你增加数据库版本号时,会触发onupgradeneeded事件,这时可能会出现成功、失败和阻止事件三种情况:
request.onerror = function(e) {
console.log(e.currentTarget.error.message);
};
request.onsuccess = function(e) {
myDB.db = e.target.result;
console.log('成功打开DB');
};
request.onupgradeneeded = function(e) {
var db = e.target.result;
if (!db.objectStoreNames.contains('person')) {
console.log("我需要创建一个新的存储对象");
//如果表格不存在,创建一个新的表格(keyPath,主键 ; autoIncrement,是否自增),会返回一个对象(objectStore)
var objectStore = db.createObjectStore('person', {
keyPath: "id",
autoIncrement: true
});
//指定可以被索引的字段,unique字段是否唯一
objectStore.createIndex("name", "name", {
unique: false
});
objectStore.createIndex("phone", "phone", {
unique: false
});
}
console.log('数据库版本更改为: ' + version);
};
onupgradeneeded事件在第一次打开页面初始化数据库时会被调用,或在当有版本号变化时。所以,你应该在onupgradeneeded函数里创建你的存储数据。如果没有版本号变化,而且页面之前被打开过,你会获得一个onsuccess事件。
2. 添加数据
a) 首先需要创建一个事务,并要求具有读写权限
var transaction = db.transaction(storeName, 'readwrite');
b) 获取objectStore,再调用add方法添加数据
var store = transaction.objectStore(storeName);
var request = store.get(key);
request.onsuccess = function(e) {
data = e.target.result;
console.log(student.name);
};
3.删除数据
删除跟新增一样,需要创建事务,然后调用删除接口,通过key删除对象。
var transaction = db.transaction(storeName, 'readwrite');
var store = transaction.objectStore(storeName);
store.delete(key);
4.查找数据
a) 按key查找
开启事务,获取objectStore,调用往get()方法,往方法里传入对象的key值,取出相应的对象
var transaction = db.transaction(storeName, 'readwrite');
var store = transaction.objectStore(storeName);
var request = store.get(key);
request.onsuccess = function(e) {
data = e.target.result;
console.log(student.name);
};
b) 使用索引查找
我们可以在创建object store的时候指明索引,使用object store的createIndex创建索引,方法有三个参数:索引名称、索引属性字段名、索引属性值是否唯一。
objectStore.createIndex("name", "name", {
unique: false
});
如上代码中,我们建好了name索引,就可以用该索引来进行查询了:
var transaction = db.transaction(storeName);
var store = transaction.objectStore(storeName);
var index = store.index(search_index);
index.get(value).onsuccess = function(e) {
data = e.target.result;
console.log(student.id);
}
c) 游标遍历数据
对数据库熟悉的同学很好理解游标的作用,有了数据库object store的游标,我们就可以利用游标遍历object store了。
var transaction = db.transaction(storeName);
var store = transaction.objectStore(storeName);
var request = store.openCursor();//打开游标
var dataList = new Array();
var i = 0;
request.onsuccess = function(e) {
var cursor = e.target.result;
if (cursor) {
console.log(cursor.key);
dataList[i] = cursor.value;
console.log(dataList[i].name);
i++;
cursor.continue();
}
data = dataList;
};
4.更新对象
更新对象,首先要把它取出来,修改,然后再放回去。
var transaction = db.transaction(storeName, 'readwrite');
var store = transaction.objectStore(storeName);
var request = store.get(key);
request.onsuccess = function(e) {
var data = e.target.result;
for (a in newData) {
//除了keypath之外
data.a = newData.a;
}
store.put(data);
};
5.关闭与删除数据库
关闭数据库可以直接调用数据库对象的close方法
function closeDB(db) {
db.close();
}
删除数据库使用数据库对象的deleteDatabase方法
function deleteDB(name) {
indexedDB.deleteDatabase(name);
}
总结
以上就是indexedDB的一些基本概念以及使用,由于篇幅原因,还有一些更深入的细节没有介绍,比如indexedDB的游标结合索引,发挥其真正的优势,有兴趣的小伙伴可以继续深入研究,还有就是要注意浏览器的支持问题,IE9以及更早的版本并不支持,火狐和谷歌浏览器没有问题,推荐使用,文章如果纰漏或者不足,欢迎指正~
前端存储之indexedDB的更多相关文章
- 前端存储之Web Sql Database
前言 在上一篇前端存储之indexedDB中说到,我们项目组要搞一个前后端分离的项目,要求在前端实现存储,我们首先找到了indexedDB,而我们研究了一段时间的indexedDB后,发现它并不是很适 ...
- 前端存储 - localStorage
发布自Kindem的博客,欢迎大家转载,但是要注意注明出处 localStorage 介绍 在HTML5中,引入了两个新的前端存储特性: localStorage sessionStorage 这两者 ...
- 前端之js-本地存储-localStorage && IndexedDB
1.LocalStorage示例 var Config = function ( name ) { //storage为空时,初始化的信息 var storage = { 'name': 'test' ...
- HTML5存储之 indexedDB
IndexeDB是HTML5 重要的一部分,它是一种轻量级的NOSQL数据库.对创建具有丰富本地存储数据的数据密集型的离线HTML5 Web 应用程序很有用. IndexedDB是为了能够在客户端存储 ...
- 前端存储loaclForage
以前使用本地存储,首先会想到localstorage或者session storage,将要存储的数据转化成字符串后进行setItem操作,但是使用local storage 有几个问题: 1.它是同 ...
- 本地存储数据库indexedDB实现离线预览的功能
今天在学习<高级JS编程>,看到离线存储,cookie和session都十分的熟悉,但是书中还提到了indexedDB和webSQL(已废弃),indexedDB可以像mysql一样建表, ...
- localStorage sessionStorage 和cookie等前端存储方式总结
localStorage sessionStorage 和cookie localStorage localStorage是本地存储的,除非清空本地数据 localStorage不会自动把数据发给服务 ...
- 前端存储 (5) - service worker 离线存储
service worker 离线存储 简介: 一般的网站 在我们无法访问的 时候 一般 回出现 如下 该网页无法访问 service worker 构建的网站不会出现这个错误,因为所有的 请求都是先 ...
- localStorage前端存储数据
<!DOCTYPE html> <html> <head> <title>localStorage演示</title> <meta c ...
随机推荐
- 如何使用 JSP JSTL 显示/制作树(tree) 菜单
JSTL里面并没有直接制作tree菜单的元素,因此递归是JSP JSTL显示/制作tree菜单的唯一方法. 以下详述如何制作tree菜单. 首先,在主页面里面增加包含制作树菜单的jsp,例如: 在my ...
- Springboot+Redis序列化坑
今天在测试springboot整合redis的时候遇到下面这个坑,百度来百度去发现提示都是ajax的问题,真的是醉了,错误提示如下所示,不信大家可以直接复制百度一下答案是什么(流泪中....),错误如 ...
- ui_modules和ui_method
## 06ui.py #coding:utf-8 import tornado.httpserver import tornado.ioloop import tornado.options impo ...
- EVERYTHING 1.3.4参数
命令行参数 操作符: space 与 (AND) | 或 (OR) ! 非 (NOT) < > 分组 " &quo ...
- C语言字节对齐问题详解【转】
引言 转自:http://www.cnblogs.com/clover-toeic/p/3853132.html 考虑下面的结构体定义: 1 typedef struct{ 2 char c1; 3 ...
- EL的函数与标签
1 什么EL函数库 EL函数库是由第三方对EL的扩展,我们现在学习的EL函数库是由JSTL添加的.下面我们会学习JSTL标签库. EL函数库就是定义一些有返回值的静态方法.然后通过EL语言来调用它们! ...
- Python的程序结构[3] -> 变量/Variable[0] -> 变量类型
变量类型 / Variable Type 在 Python 中,变量主要有以下几种,即全局变量,局部变量和内建变量, 全局变量 / Global Variable 通常定义于模块内部,大写变量名形式存 ...
- Python的网络编程[0] -> socket[2] -> 利用 socket 建立 TCP/UDP 通信
Socket 目录 socket 的 TCP/IP 通信基本建立过程 socket 的 UDP 通信基本建立过程 socket 的 UDP 广播式通信基本建立过程 socket 的多线程通信建立过程 ...
- Ubuntu下触控板手势调节软件xSwipe
楼主进了一台Thinkpad T450s,触控板支持4点触控,安装了ubuntu14.04 LTS之后,触控板只剩下双指滑动了,略有不爽,各种google,百度. 真找到办法了. 首先得知了touch ...
- SOAP、SOCKET协议
一.SOAP( SOAP:Simple Object Access Protocol) 简单对象访问协议,简单对象访问协议(SOAP)是一种轻量的.简单的.基于 XML 的协议,它被设计成在 WEB ...