Web数据持久化存储IndexedDB(不常用)
IndexedDB是在浏览器中保存结构化数据的一种数据库,为了替换WebSQL(标准已废弃,但被广泛支持)而出现。IndexedDB使用NoSQL的形式来操作数据库,保存和读取是JavaScript对象,同时还支持查询及搜索。
下面由5个方面讲述:
1. 数据库初始化
2. 对象存储空间(ObjectStore)
3. 事务
4. 游标查询
5. 索引
数据库初始化
IndexedDB保存的是对象,而不是使用表保存数据。打开数据库使用indexDB.open方法,这方法有两个参数,第一个是数据库名称,第二个是数据版本号。
PS:IndexedDB的操作完全是异步进行的,每一次IndexedDB操作,都需要注册onerror或onsuccess事件处理程序。
var DB_NAME = 'DEMO';
var DB_VERSION = 2; //使用正整数,别用浮点型
var db; function initDb() {
console.debug("initDb ...");
var req = indexedDB.open(DB_NAME, DB_VERSION);
req.onsuccess = function (evt) {
db = evt.target.result;
console.debug("initDb opened");
};
req.onerror = function (evt) {
console.error("initDb error:", evt.target.errorCode || evt.target.error);
}; //增加数据库版本号时,会触发onupgradeneeded事件(会在onsuccess之前被调用)
req.onupgradeneeded = function (evt) {
console.debug("initDb.onupgradeneeded");
};
}
PS:这里要注意的是,数据库版本只会有最新一个,不会同时存在两个版本的同名数据库。
对象存储空间(ObjectStore)
对象存储空间(ObjectStore)可以想象成关系数据库的表,在初始化DB触发onupgradeneeded时,创建ObjectStore。使用createObjectStore方法,第一个参数是对象名,第二个参数是对象属性,一般是设置keyPath(作为键使用)。
req.onupgradeneeded = function (evt) {
console.debug("initDb.onupgradeneeded");
var db = evt.currentTarget.result;
//ObjectStore必须在onupgradeneeded里创建,其他地方将会创建失败
var usersStore = db.createObjectStore("users", { keyPath : "id" });
};
效果如下:
事务
所有读取或修改数据的操作,都要通过事务来完成。创建事务使用transaction方法,第一个参数是需要访问的ObjectStore,第二个参数是访问模式(readwrite、readonly,默认是只读)。
添加数据
function addData(){
var users = [{
id : '001',
name : '刘亦菲',
age : 18
},{
id : '002',
name : '杨幂',
age : 19
}]; var tx = db.transaction("users", READ_WRITE);
var store = tx.objectStore("users");
var i = 0, len = users.length;
while(i < len){
store.add(users[i++]);
}
}
获取数据
function getData(){
var tx = db.transaction("users");
var store = tx.objectStore("users");
var req = store.get("001");
req.onsuccess = function (evt) {
var res = evt.target.result;
console.debug(res);
};
req.onerror = function (evt) {
console.error("getData error:", evt.target.errorCode || evt.target.error);
};
}
修改数据
function updateData(){
var tx = db.transaction("users", READ_WRITE);
var store = tx.objectStore("users");
var req = store.put({
id : '001',
name : '刘亦菲-小龙女',
age : 18
});
req.onsuccess = function (evt) {
console.debug("updateData success");
};
req.onerror = function (evt) {
console.error("updateData error:", evt.target.errorCode || evt.target.error);
};
}
删除数据
function delData(){
var tx = db.transaction("users", READ_WRITE);
var store = tx.objectStore("users");
var req = store.delete("001");
req.onsuccess = function (evt) {
console.debug("delData success");
};
req.onerror = function (evt) {
console.error("delData error:", evt.target.errorCode || evt.target.error);
};
}
清空数据
function clearData(){
var tx = db.transaction("users", READ_WRITE);
var store = tx.objectStore("users");
var req = store.clear();
req.onsuccess = function (evt) {
console.debug("clearData success");
};
req.onerror = function (evt) {
console.error("clearData error:", evt.target.errorCode || evt.target.error);
};
}
游标查询
使用事务可以直接通过键检索单个对象,而需要检索多个对象时候就需要使用游标。游标是指向结果集的指针,不提前收集结果。游标指针会先指向结果中的第一项,在接到查找下一项指令时,才会指向下一项。
function openCursor(){
var tx = db.transaction("users", READ_WRITE);
var store = tx.objectStore("users");
var req = store.openCursor();
req.onsuccess = function (evt) {
var cursor = evt.target.result;
if(cursor){ //必要检查
var value = cursor.value;
console.log(value);
if(value.name == '杨幂'){
value.age = 16;
cursor.update(value); //修改数据(必须是读写模式)
}
if(value.name == '柳岩'){
cursor.delete(); //删除当前项
}
cursor.continue(); //移动到下一项
}
};
req.onerror = function (evt) {
console.error("openCursor error:", evt.target.errorCode || evt.target.error);
};
}
这里有几点要注意:
1. 如果需要修改或删除数据,就需要打开成读写模式。
2. cursor的非空校验是必要的。
3. 修改或删除的操作也是有onsuccess和onerror的,只是在示例中没有写出来。
4. 调用continue才会移动到下一项
另外可以设置游标的键范围和游标的方向,即打开openCursor方法时可以传这两个参数(openCursor(键范围,方向)),第一个参数是object类型,第二个参数是字符串类型。
游标键范围
键范围由IDBKeyRange的实例表示。
IDBKeyRange.only('001'); //只想要键为001的结果
IDBKeyRange.lowerBound('002'); //从键为002开始,到最后
IDBKeyRange.lowerBound('002', true); //从键为002开始,但忽略002,到最后
IDBKeyRange.upperBound('002'); //从头开始,到键为002为止
IDBKeyRange.upperBound('002', true); //从头开始,到键为002为止,但忽略002
IDBKeyRange.bound('001', '005'); //从001开始,到为005为止
IDBKeyRange.bound('001', '005', true, true); //从001开始,到为005为止,但忽略001、005
游标方向
next : 从第一项到最后一项(默认)
prev : 从最后一项到第一项
索引
当需要使用其他属性(非主键)获取数据时,就要预先创建索引,然后使用索引获取数据。
创建索引(在数据库初始化onupgradeneeded事件时)
第一个参数是索引名字,第二个参数是索引的属性的名字,第三个是一个options对象。一般是指定unique,设置索引是否唯一。
usersStore.createIndex("name", "name", { unique : false });
索引获取数据
function indexGetData(){
var tx = db.transaction("users", READ_WRITE);
var store = tx.objectStore("users");
var index = store.index("name");
var req = index.get("杨幂")
req.onsuccess = function (evt) {
console.debug("indexGet success" , evt.target.result);
};
req.onerror = function (evt) {
console.error("indexGet error:", evt.target.errorCode || evt.target.error);
};
} function indexOpenCursor(){
var tx = db.transaction("users", READ_WRITE);
var store = tx.objectStore("users");
var index = store.index("name");
var req = index.openCursor();
req.onsuccess = function (evt) {
var cursor = evt.target.result;
if(cursor){ //必要检查
var value = cursor.value;
console.log(value);
cursor.continue(); //移动到下一项
}
};
req.onerror = function (evt) {
console.error("openCursor error:", evt.target.errorCode || evt.target.error);
};
}
PS:索引用法跟普通取值和游标取值一样
对象存储所有索引
function indexNames(){
var tx = db.transaction("users", READ_WRITE);
var store = tx.objectStore("users");
var indexNames = store.indexNames;
var index, i = 0, len = indexNames.length;
while(i < len){
index = store.index(indexNames[i++]);
console.log(index);
}
}
浏览器支持情况
PS:图表来源->http://caniuse.com/#feat=indexeddb
总结
在使用IndexedDB时候,有人可能会拿WebSQL来比较,然后发现IndexedDB不能做表连接(因为根本没有这东西),也就是要查出一个数据,可能得分几次进行。
例如学生、课程、分数三个表数据,想查出某个学生的课程成绩,就得三个表连接,WebSQL分分钟信手拈来。但是如果你用IndexedDB,就得分三次查找,先拿出那个学生,再拿出课程,然后再拿成绩。
这样看起来IndexedDB很蠢,这样就进入误区了,你为什么要这么去存你要展示的数据,NoSql就用NoSql东西,就直接以一个对象存学生成绩,一次查找就行了。
示例下载:http://files.cnblogs.com/files/lovesong/IndexedDBdemo.zip
本文为原创文章,转载请保留原出处,方便溯源,如有错误地方,谢谢指正。
本文地址 :http://www.cnblogs.com/lovesong/p/5055384.html
Web数据持久化存储IndexedDB(不常用)的更多相关文章
- iOS数据持久化存储:归档
在平时的iOS开发中,我们经常用到的数据持久化存储方式大概主要有:NSUserDefaults(plist),文件,数据库,归档..前三种比较经常用到,第四种归档我个人感觉用的还是比较少的,恰恰因为用 ...
- vuex数据持久化存储
想想好还是说下vuex数据的持久化存储吧.依稀还记得在做第一个vue项目时,由于刚刚使用vue,对vue的一些基本概念只是有一个简单的了解.当涉及到非父子组件之间通信时,选择了vuex.只是后来竟然发 ...
- iOS开发——数据持久化Swift篇&使用Core Data进行数据持久化存储
使用Core Data进行数据持久化存储 一,Core Data介绍 1,Core Data是iOS5之后才出现的一个数据持久化存储框架,它提供了对象-关系映射(ORM)的功能,即能够将对象转化成 ...
- Swift - 使用Core Data进行数据持久化存储
一,Core Data介绍 1,Core Data是iOS5之后才出现的一个数据持久化存储框架,它提供了对象-关系映射(ORM)的功能,即能够将对象转化成数据,也能够将保存在数据库中的数据还原成对象. ...
- [Xcode 实际操作]七、文件与数据-(14)数据持久化存储框架CoreData的使用:删除CoreData中的数据
目录:[Swift]Xcode实际操作 本文将演示如何删除数据持久化对象. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] import UIKit //引入数据持 ...
- [Xcode 实际操作]七、文件与数据-(13)数据持久化存储框架CoreData的使用:编辑CoreData中的数据
目录:[Swift]Xcode实际操作 本文将演示如何修改数据持久化对象. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] import UIKit //引入数据持 ...
- [Xcode 实际操作]七、文件与数据-(12)数据持久化存储框架CoreData的使用:查找CoreData中的数据
目录:[Swift]Xcode实际操作 本文将演示如何查找数据持久化对象. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] import UIKit //引入数据持 ...
- [Xcode 实际操作]七、文件与数据-(11)数据持久化存储框架CoreData的使用:创建CoreData实体并插入数据
目录:[Swift]Xcode实际操作 本文将演示[CoreData]数据持久化存储框架的使用. 点击[Create a new Xcode project]创建一个新的项目 ->[Single ...
- 转载 -- iOS数据持久化存储
作者:@翁呀伟呀 授权本站转载 概论 所谓的持久化,就是将数据保存到硬盘中,使得在应用程序或机器重启后可以继续访问之前保存的数据.在iOS开发中,有很多数据持久化的方案,接下来我将尝试着介绍一下5种方 ...
随机推荐
- Cocos2d-x 3.2 学习笔记(十一)Game 2048
一.规则 游戏2048的规则很简单 2+2=4 4+4=8 8+8=16 16+16=32 ……1024+1024=2048 这游戏挺火的……不过做起来也不难,就用cocos2dx做一下,首先我也没 ...
- Android基于mAppWidget实现手绘地图(十二)–显示当前用户位置
若显示当前用户位置,你需要执行以下步骤: 1.添加ACCESS_COARSE_LOCATION 和ACCESS_FINE_LOCATION权限在AndroidManifest.xml中 2.用mapW ...
- 学习网页制作中如何在正确选取和使用 CSS 单位
在 CSS 测量系统中,有好几种单位,如像素.百分比.英寸.厘米等等,Web 开发人员很难了解哪些单位在何处使用,如何使用.很多人习惯了总是使用同一种单位,但这一决定可能会严重限制你的设计的执行. 这 ...
- 帮助你实现漂亮界面的14套免费的 HTML/CSS 源码
在网络上能找很多免费的 PSD 格式素材,但是很少有 HTML/CSS 界面组件下载.在这篇文章中,收集了14套免费的 HTML/CSS 界面源码分享给前端设计师和开发者们.这些组件包括按钮.滑块.表 ...
- ajax检查用户名是否存在
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.c ...
- emacs: 文本输入中文件目录自动补全
emacs: 文本输入中文件目录自动补全 // */ // ]]> UP | HOME emacs: 文本输入中文件目录自动补全 Table of Contents 1 引言 2 补全过程演 ...
- caffe 试运行MNIST
转自:http://www.cnblogs.com/NanShan2016/p/5469942.html 编译完caffe后,在D:\caffe\caffe-master\caffe-master\b ...
- C#指定时间和当前时间的相差的月份、天数
DateTime 类型有时间的 年月日时分秒等属性,但是获取两个DateTime的 相差月份,就需要自己写了: public static int GetSubMonth(DateTime speci ...
- 用php怎么写一个用户注册登录的页面呢?
想写就会尽快去写.如果用php写了就一定要用nodejs写出来啊,不写是小狗啊! 补充一下,想要实现的功能: 1.用户名重复检测 2.检测信息填写是否完整 3.邮箱是否已经被注册 4.实现ajax无刷 ...
- Winform开发框架之读卡器和条码扫描枪的数据接收处理
在我们开发一些项目的时候,一般需要一些外围的设备进行数据处理,如ID/IC读卡器获取卡号.激光条码扫描枪.USB摄像头.USB方式的小票据打印机(POS打印机).USB来电录音盒.普通打印机等一系列附 ...