IndexedDB完全指南

作者原创:Chibuike Nwachukwu
原文地址:https://blog.logrocket.com/using-indexeddb-complete-guide/
翻译:井川
1写在前面 数据存储是大多数web
应用程序的重要组成部分,从用户数据跟踪到应用程序数据。随着更快、更强大的Web
应用程序的快速开发,需要高效的客户端存储来帮助开发。
web
上的客户端存储多年来发生了很大变化,从用于存储用户数据的cookies
到 WebSQL
(当前已弃用)这允许开发人员将数据存储在浏览器内的SQL
数据库中,这使得了解SQL
的用户可以轻松创建强大的应用程序。
IndexedDB
是 WebSQL
的替代品,它提供比以前的实例更多的存储容量。在本教程中,我们将探索如何使用和配置 IndexedDB
来存储 Web
应用程序的数据,以及如何使用可用的 API 操作其数据。
2IndexedDB
是什么?
IndexedDB
是用于客户端存储的低级 API
。它是一个成熟、持久的NoSQL
存储系统,可在浏览器中使用,并允许您存储不同类型的数据,例如:
- 文件或Blob
- 图像和视频
- 结构
IndexedDB
可用于缓存、PWA
、游戏等多种场景,还支持交易。它的开发是为了有效地满足web
应用程序的各种需求。
3 设置我们的项目
我们不会进行任何花哨的设置,因为 IndexedDB
在网络上本地运行。首先,创建一个新目录来安装项目:
mkdir indexed-db && cd indexed-db
现在我们将通过创建脚本来创建一个文件来查看我们的应用程序 index.js
index.html
一个要存储的文件我们的应用程序逻辑:
touch index.html index.js styles.css
4 在索引数据库中存储数据
要了解使用此数据库的好处并了解如何与 API
进行交互,我们将创建一个基本任务应用程序。让我们启用一个添加函数来查看数据如何保存到数据库,另一个函数来查看所有任务,以及一个删除函数来查看 GET
和 的
。 API
功能删除
打开在上一节中创建的index.html
并添加以下代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TODO APP</title>
<script defer></script>
<link href="style.css" rel="stylesheet">
</head>
<body>
<h1>TODO APP</h1>
<section>
<aside class="view">
<h2>TODOs</h2>
<div class="todos">
<ol></ol>
</div>
</aside>
<aside class="add">
<h2>Add Todo</h2>
<form>
<div>
<label for="title">Todo title</label>
<input id="title" type="text" required>
</div>
<div>
<label for="desc">Todo description</label>
<input id="desc" type="text" required>
</div>
<div>
<button>Save</button>
</div>
</form>
</aside>
</section>
</body>
</html>
这将创建我们的Web
应用程序的基础架构。我们在这里主要做两件事:首先,我们创建一个部分来显示/查看数据库中存储的所有任务项,其次,我们创建一个部分来将任务项添加到数据库中。
我们还为应用程序添加了一些基本样式。打开文件 styles.css
并添加以下内容:
html {
font-family: sans-serif;
}
body {
margin: 0 auto;
max-width: 800px;
}
header, footer {
background-color: blue;
color: white;
padding: 0 20px;
}
.add, .view {
padding: 30px;
width: 40%;
}
.add {
background: #ebe6e6;
}
section {
padding: 10px;
background: #3182d4;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
}
h1 {
margin: 0;
}
ol {
list-style-type: none;
}
div {
margin-bottom: 10px;
}
文件 index.js
是应用程序的核心,因为它包含应用程序中使用的文件和 IndexedDB
之间的互动逻辑。
首先我们需要创建一个数据库;然后,我们可以通过创建一个对象存储(类似于 SQL
中的表)来初始化它,我们将使用该对象存储来存储每个项目的详细信息。打开文件 index.js
,添加以下逻辑:
let db;
const openOrCreateDB = window.indexedDB.open('todo_db', 1);
openOrCreateDB.addEventListener('error', () => console.error('Error opening DB'));
openOrCreateDB.addEventListener('success', () => {
console.log('Successfully opened DB');
db = openOrCreateDB.result;
});
openOrCreateDB.addEventListener('upgradeneeded', init => {
db = init.target.result;
db.onerror = () => {
console.error('Error loading database.');
};
const table = db.createObjectStore('todo_tb', { keyPath: 'id', autoIncrement:true });
table.createIndex('title', 'title', { unique: false });
table.createIndex('desc', 'desc', { unique: false });
});
如上所示,创建了一个名为 index.js
的数据库,然后创建了一个名为 的对象存储创建了 todo_db ,其中包含两个索引:title
和 desc
。这些索引允许它们的值在存储中重复,类似于在SQL
中创建表,然后创建两列。
然后,要添加功能保存
,我们继续检索在表单中输入的值,然后将它们存储到数据库中:
const todos = document.querySelector('ol');
const form = document.querySelector('form');
const todoTitle = document.querySelector('#title');
const todoDesc = document.querySelector('#desc');
const submit = document.querySelector('button');
form.addEventListener('submit', addTodo);
function addTodo(e) {
e.preventDefault();
const newTodo = { title: todoTitle.value, body: todoDesc.value };
const transaction = db.transaction(['todo_tb'], 'readwrite');
const objectStore = transaction.objectStore('todo_tb');
const query = objectStore.add(newTodo);
query.addEventListener('success', () => {
todoTitle.value = '';
todoDesc.value = '';
});
transaction.addEventListener('complete', () => {
showTodos();
});
transaction.addEventListener('error', () => console.log('Transaction error'));
}
将值添加到存储后,两种表单都将清除字段,以便用户可以将新项目添加到他们的列表中。我们可以通过调用 showTodos
方法来更新视图,我们将在下一节中看到。
5 检索和显示数据
要检查“保存任务”功能是否正常工作,请在浏览器中打开并使用检查功能。在 Chrome
中,您可以在应用程序选项卡下的存储中看到 IndexedDB
。如下图所示,我们创建了一个数据库,并将第一个任务项存储在 todo_tb
对象存储中:
在用户加载页面时显示可用的任务项,并提供一个视图对于之前添加和删除的任务项,我们将创建一个名为 showTodos
:
function showTodos() {
while (todos.firstChild) {
todos.removeChild(todos.firstChild);
}
const objectStore = db.transaction('todo_tb').objectStore('todo_tb');
objectStore.openCursor().addEventListener('success', e => {
const pointer = e.target.result;
if(pointer) {
const listItem = document.createElement('li');
const h3 = document.createElement('h3');
const pg = document.createElement('p');
listItem.appendChild(h3);
listItem.appendChild(pg);
todos.appendChild(listItem);
h3.textContent = pointer.value.title;
pg.textContent = pointer.value.body;
listItem.setAttribute('data-id', pointer.value.id);
const deleteBtn = document.createElement('button');
listItem.appendChild(deleteBtn);
deleteBtn.textContent = 'Remove';
deleteBtn.addEventListener('click', deleteItem);
pointer.continue();
} else {
if(!todos.firstChild) {
const listItem = document.createElement('li');
listItem.textContent = 'No Todo.'
todos.appendChild(listItem);
}
console.log('Todos all shown');
}
});
}
的方法,此方法从存储中检索 Todos 项,迭代每个项,并创建一个 A HTML
元素。将项目添加到网页上的列表项 ol
,将每个任务项的 id
传递到名为 data-id
的数据属性。稍后,当我们介绍 deleteItem
函数时,当我们需要从内存中删除它时,我们将使用这个唯一的 ID
来标识每个任务。
要在页面加载时获取任务项,请将成功事件监听器 openOrCreateDB
更改为:
openOrCreateDB.addEventListener('success', () => {
console.log('Successfully opened DB');
db = openOrCreateDB.result;
showTodos();
});
6 从数据库中删除数据
最后,让我们测试一下该数据库 DELETE API
并为我们的待办事项列表应用程序创建一个函数 删除
:
function deleteItem(e) {
const todoId = Number(e.target.parentNode.getAttribute('data-id'));
const transaction = db.transaction(['todo_tb'], 'readwrite');
const objectStore = transaction.objectStore('todo_tb');
objectStore.delete(todoId);
transaction.addEventListener('complete', () => {
e.target.parentNode.parentNode.removeChild(e.target.parentNode);
alert(`Todo with id of ${todoId} deleted`)
console.log(`Todo:${todoId} deleted.`);
if(!todos.firstChild) {
const listItem = document.createElement('li');
listItem.textContent = 'No Todo.';
todos.appendChild(listItem);
}
});
transaction.addEventListener('error', () => console.log('Transaction error'));
}
这将使用唯一的 ID
删除指定的任务项目,并从页面中删除该项目。删除内存中的最后一个任务后,在任务列表位置显示“无任务项”消息。
要确认任务项已从数据库中删除,请继续检查网页并单击“应用程序”选项卡。如您所见,对象存储 todo_tb
现在不包含任何项目:
最终应用程序 Web
如下所示:
7 索引数据库的增量版本
IndexedDB还允许开发人员增加数据库版本。打开数据库时,指定所需的版本号:
window.indexedDB.open('todo_db', 1);
如果数据库不存在,则会使用指定的版本创建数据库。如果数据库已经存在,则检查版本号。
如果调用open
方法时指定的版本号高于现有版本,则通过onUpgradeNeeded
事件触发版本变更事件。此事件允许您执行数据库架构更改或数据迁移。
需要注意的一点是,删除之前的商品商店以添加新选项,创建新商品也会删除旧商店中的所有其他数据。在升级数据库之前,读取旧内容并将其存储在其他地方。
8 使用索引数据库的缺点
由于 IndexedDB
依赖于客户端的 web
浏览器,因此它通常更适合个人用户或小型应用程序。虽然它可以处理大量数据,但在大型应用程序或多人使用的应用程序中使用IndexedDB
时存在一些问题。
可扩展性限制
IndexedDB
在Web 浏览器
中运行,这意味着它受到客户端环境的功能和资源的限制。它可能不太适合需要处理大量并发用户或极高吞吐量的场景。
数据大小限制
不同的网络浏览器对
IndexedDB
中可以存储的最大数据量设置限制。这些限制因浏览器而异,范围可以从几兆字节到数百兆字节。
了解这些限制并相应地设计您的应用程序非常重要。当数据存储空间耗尽时,您将无法将新数据保存到数据库,因为会引发错误QuotaExceededError
。
同步挑战
IndexedDB
没有提供内置机制来管理客户端之间的数据同步或处理分布式环境中的冲突。您必须实现自定义同步逻辑来处理这些场景。维护不同应用程序实例之间的数据一致性和同步变得复杂。
因此,对于大型应用或者多人使用的应用,使用服务器端数据库或者云存储方案会更加高效。
9 写在最后
在这篇文章中,我们了解了 IndexedDB
,web
上的数据库以及如何使用 JavaScript
与其互动存储数据应用程序Web
。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。