IndexedDB 是一种将数据持久存储在用户浏览器中的方法。因为它允许您创建具有丰富查询能力的 Web 应用程序,而不管网络可用性如何,这些应用程序可以在线和离线工作。IndexedDB 对于存储大量数据的应用程序(例如,借阅图书馆中的 DVD 目录)和不需要持续 Internet 连接即可工作的应用程序(例如,邮件客户端、待办事项列表和记事本)。
IndexedDB 允许您存储和检索使用“键”索引的对象。您对数据库所做的所有更改都发生在事务中。像大多数 Web 存储解决方案一样,IndexedDB 遵循同源策略. 因此,虽然您可以访问域内存储的数据,但您无法跨不同域访问数据。
如果您有使用其他类型数据库的假设,则在使用 IndexedDB 时可能会被抛弃。因此,要记住 IndexedDB 的以下关键特征很重要:
IndexedDB 数据库存储键值对。值可以是复杂的结构化对象,键可以是这些对象的属性。您可以创建使用对象的任何属性进行快速搜索以及排序枚举的索引。键可以是二进制对象。
IndexedDB 建立在事务数据库模型之上。你在 IndexedDB 中所做的一切总是发生在事务的上下文中. IndexedDB API 提供了许多表示索引、表、游标等的对象,但每个对象都与特定事务相关联。因此,您不能在事务之外执行命令或打开游标。事务具有明确定义的生命周期,因此在事务完成后尝试使用它会引发异常。此外,事务自动提交,不能手动提交。当您考虑如果用户同时在两个不同的选项卡中打开您的 Web 应用程序的两个实例时可能发生的情况时,此事务模型非常有用。如果没有事务操作,两个实例可能会干扰彼此的修改。如果您不熟悉数据库中的事务,请阅读维基百科关于交易的文章. 另请参阅定义部分下的交易。
IndexedDB API 主要是异步的。API 不会通过返回值为您提供数据;相反,您必须传递一个回调函数。您不会将值“存储”到数据库中,也不会通过同步方式从数据库中“检索”值。相反,您“请求”发生数据库操作。当操作完成时,您会收到 DOM 事件的通知,并且您收到的事件类型让您知道操作是成功还是失败。起初这听起来有点复杂,但里面有一些健全的措施。这与XMLHttpRequest 的工作方式没有什么不同。
IndexedDB 使用了很多请求。 请求是接收前面提到的成功或失败 DOM 事件的对象。他们有 onsuccess 和 onerror 属性,你可以打电话 addEventListener() 和 removeEventListener() 他们。他们也有 readyState, result和 errorCode 性质,告诉你的请求的状态。该 result 属性特别神奇,因为它可以是许多不同的东西,这取决于请求的生成方式(例如,一个 IDBCursor 实例,或者您刚刚插入到数据库中的值的键)。
IndexedDB 使用 DOM 事件在结果可用时通知您。 DOM 事件总是有一个 type 属性(在 IndexedDB 中,它最常设置为 "success" 或 "error")。DOM 事件还有一个 target 属性来指示事件的走向。在大多数情况下, target 事件的IDBRequest 对象是由于执行某些数据库操作而生成的 对象。成功事件不会冒泡,也无法取消。另一方面,错误事件会冒泡,并且可以取消。
IndexedDB 是面向对象的。IndexedDB 不是一个关系数据库,它的表代表行和列的集合。这一重要而根本的区别会影响您设计和构建应用程序的方式。在传统的关系数据存储中,您会有一个表来存储数据行和指定数据类型的列的集合。另一方面,IndexedDB 要求您为某种类型的数据创建一个对象存储并将 JavaScript 对象持久化到该存储中。每个对象存储都可以有一个索引集合,这使得查询和迭代变得高效。
IndexedDB 不使用结构化查询语言 (SQL)。它使用对生成游标的索引进行查询,您可以使用该游标在结果集上进行迭代。
IndexedDB 遵循同源策略。源是执行脚本的文档的 URL 的域、应用层协议和端口。每个源都有自己关联的一组数据库。每个数据库都有一个名称,用于在源中标识它。
示例代码:
<script type="text/javascript">
if ('indexedDB' in window) {
// 如果数据库不存在则创建,如果存在但是version更大,会自动升级不会复制原来的版本
var req = indexedDB.open("TestDB", 1);
req.onupgradeneeded = function(e) {
var db = req.result;
// var store = db.createObjectStore("student", {autoIncrement: true}); 使用自增键
// 创建student表
var store = db.createObjectStore("student", {keyPath: 'id'});
// 设置id为主键
store.createIndex('student_id_unqiue','id', {unique: true});
}
req.onsuccess = function(event) {
var students = [
{id: 1, name: '小叶', age: '11'},
{id: 2, name: '小王', age: '12'},
{id: 3, name: '小张', age: '13'}
];
var db = event.target.result;
// var transaction = db.transaction('student', 'readwrite');
var transaction = db.transaction(['student'], 'readwrite');
transaction.onsuccess = function(event) {
console.log('[Transaction] 好了!');
};
var studentsStore = transaction.objectStore('student');
students.forEach(function(student){
var db_op_req = studentsStore.add(student);
db_op_req.onsuccess = function() {
console.log("存好了");
}
});
studentsStore.count().onsuccess = function(event) {
console.log('学生个数', event.target.result);
};
// 获取id为1的学生
studentsStore.get(1).onsuccess = function(event) {
console.log('id为1的学生', event.target.result);
};
// 更新id为1的学生
students[0].name = '小小叶';
studentsStore.put(students[0]).onsuccess = function(event) {
console.log('更新id为1的学生姓名', event.target.result);
};
// 删除id为2的学生
studentsStore.delete(2).onsuccess = function(event) {
console.log('id为2的学生已经删除');
};
}
req.onerror = function() {
console.log("数据库出错");
}
}else{
console.log('你的浏览器不支持IndexedDB');
}
</script>

翻译文章:https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Basic_Terminology
网友回复