一、背景
Redis的数据存储位置是在服务器内存中,它的目的是是获取数据更快;indexedDB是在客户端的本地存储中,它想要解决的问题是存储更多的数据,相较于localStorage、sessionStorage。
这篇文章想讲的是indexedDB,用于将网页中所要用到的数据存储在本地中,使用索引实现对数据的高性能搜索。
二、indexedDB数据库
2.1 indexedDB 的特点
- 非关系型数据库:数据以键值对的方式存储。
- 持久化存储:像cookie、localStorage以及sessionStorage本地存储是存储在浏览器缓存中,一旦缓存被清除,数据都将被清除掉,但是indexedDB所保存的数据不会,它只能通过手动删除来清除数据。
- 异步操作
- 支持事务:当事务中的操作发生错误时,会进行回退。
- 同源策略:网页只能访问自身域名下的数据库,无法访问跨域的数据库。
- 存储容量大。
2.2 使用indexedDB数据库基本步骤
- 获取浏览器indexedDB对象。
- 打开数据库 =>得到返回值request。
- 从request中得到数据库对象。
- 数据库对象中获取仓库对象进行操作。 => mysql等数据库中是表,而indexedDB是仓库
三、方法拆解,知识点汇总。
获取浏览器indexedDB对象
// 这个做法是因为 不同的浏览器获取indexedDB的方式不一样。
// mozIndexedDB:火狐浏览器内核;webkitIndexedDB:webkit内核;msIndexedDB:IE内核。
window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
打开数据库对象
var request = window.indexedDB.open(Dynamo,DBversion); //开启数据库对象并返回请求对象
给请求对象设置监听事件,该对象可以设置三种监听事件,success、error 以及 onupgradeneeded。
success 是请求成功所要执行的监听事件。
error 是请求失败后所要执行的监听事件。
onupgradeneeded 是版本升级之后所要执行的监听事件。版本升级怎么判定:上述打开数据库函数接收了一个数据库版本号DBversion,该参数与之前的值不同就表示要升级。
request.onerror = function(event){alert("数据库连接失败:" + event.target.errorCode);
}
let db; //用于接收数据库对象
request.onsuccess = function(event){db = event.target.result;//连接成功时获取数据库对象(也可以用request.result)alert("数据库连接成功!");
}
request.onupgradeneeded = function(event){Alert(“版本更新”);
}
在数据库中创建仓库,删除仓库,获取仓库对象
新建仓库
var store = db.createObjectStore(name,option); //返回仓库对象
这里面的option包含两个选项,一个是keyPath、一个是autoIncrement。
keyPath:键路径,类似mysql中的主键。
autoIncrement:是否自增长。
db.deleteObjectStore(name) //删除仓库
创建索引
store.createIndex(索引名,索引所对应的键名,{unique:true|false});
判断仓库是否存在
db.objectStoreNames.contains(“books”);
indexedDB 事务
事务模式
readonly:只读访问,在查询对象存储时使用。
readwrite:提供对某个对象存储的读取和写入访问权。
versionchange:提供读取和写入访问权来修改对象存储定义,或者创建一个新的对象存储。
var transaction = db.transaction(“books”,”readwrite”); //为一个对象仓库创建一个读写事务
//从事务获取对象仓库
var objectStore = transaction.objectStore(“books”); //事务获取对象仓库
为仓库添加监听事件
abort:事务中断
complete:事务完成
error:事务出错
var transaction = db.transaction(“books”,”readwrite”);
transaction.oncomplete = function(event){}
transaction.onerror = function(event){}
transaction.onbort = function(event){}
数据库的增、删、改、查。
//这里的objectStore 是获取到的数据库仓库对象。
//数据库的条目的增加
objectStore.add(objectName);
//数据库内容的修改
objectStore.put(objectName); //修改是键值相同
//数据库条目的删除
objectStore.delete(objectName);
//清空数据库仓库
objectStore.clear() //清空objectStore
//数据库数据的读取
var request = objectStore.get(value);
事件监听
request.onerror = function(event){}
request.onsuccess = function(event){}
游标遍历
//游标遍历的打开可以通过利用对象仓库(根据主键,keyPath),也可以通过索引
//获取到仓库对象 objectStore
//由仓库对象打开游标
var cursor = objectStore.openCursor();//由索引打开
//获取仓库对象的索引
var index = objectStore.index(indexName);
Var cursor = index.openCursor();cursor.onsuccess = function(e){//获取结果集var result = e.target.result;if(result){result.continue();}else{Console.log(“遍历完成!”);}
}
最后还有一方面的知识是 IDBKeyRange 根据键值的大小来搜索。(用于设置范围供给openCursor使用)
var keyRangeValue = IDBKeyRange.bound(“A”,”F”,true|false,true|false); //上下限 x< 值 <y
//这里的true表示不包括等于,false代表包括等于
objectStore.openCursor(keyRangeValue).onsuccess = function(event){}IDBKeyRange.upperBound(x) //<=x
IDBKeyRange.upperBound(x,true) // <x
IDBKeyRange.lowerBound(y) //>=y
IDBKeyRange.lowerBound(y,true) //>y
IDBKeyRange.only(x) // =
IDBKeyRange.includes(x,y,z) //包括
思维导图
四、例子讲解
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body></body>
<script>// In the following line, you should include the prefixes of implementations you want to test.// window.mozIndexedDB 火狐浏览器内核 window.webkitIndexedDBwindow.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;// DON'T use "var indexedDB = ..." if you're not in a function.// Moreover, you may need references to some window.IDB* objects:window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction || {READ_WRITE: "readwrite"}; // This line should only be needed if it is needed to support the object's constants for older browserswindow.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;// (Mozilla has never prefixed these objects, so we don't need window.mozIDB*)if (!window.indexedDB) {console.log("Your browser doesn't support a stable version of IndexedDB. Such and such feature will not be available.");}else{console.log("有indexedDB。");}let db; //用于存储连接成功后返回的数据库对象//DBName 是数据库名 DBVersion 数据库版本var request = window.indexedDB.open("MyBook", 1);request.onerror = function(event){alert("数据库连接失败:" + event.target.errorCode);}request.onsuccess = function(event){console.log(event);db = event.target.result;//连接成功时获取数据库对象(也可以用request.result)alert("数据库连接成功!");var trans = db.transaction("myBooks","readwrite"); //为仓库对象创建读写事务//给事务添加监听事件trans.oncomplete = function(event){console.log(event);console.log("事务结束!");}trans.onerror = function(event){console.log("Error:", event.target.error.name)}//这是添加事务里面所要运行的代码var bookStore = trans.objectStore("myBooks"); //获取仓库对象的事务bookStore.put({"name":"宿命","isbn":"isbn002","price":35});console.log(db.objectStoreNames.contains("myBooks"));}request.onupgradeneeded = function(event){var db = event.target.result;//数据库仓库中内容发生变化所要的更新写在这里var objectStore = db.createObjectStore("myBooks",{keyPath:"isbn"}); //仓库对象objectStore.createIndex("name","name",{unique:false}); //给仓库对象加索引objectStore.createIndex("price","price",{unique:false});var bookList = [{"name":"微尘","isbn":"isbn001","price":31},{"name":"红手指","isbn":"isbn002","price":25},{"name":"时生","isbn":"isbn003","price":19},{"name":"非暴力沟通","isbn":"isbn004","price":41}]var request;for (var item of bookList){request = objectStore.add(item);request.onsuccess = function(event){console.log(event);console.log("数据存储成功");}request.onerror = function(event){console.log(event);console.log("数据存储失败。");}}}
</script>
</html>
在浏览器中看本地存储的indexedDB所存储的信息。
上述代码输出