IndexDB完整使用指南

IndexDB完整使用指南

数据存储是大多数 Web 应用程序的重要组成部分,从跟踪用户数据到应用程序数据。随着更快、更强大的 Web 应用程序的快速开发,需要高效的客户端存储来帮助开发。

多年来,Web 上的客户端存储已经发生了很大的变化,从用于存储用户数据的 cookieWebSQL(目前已弃用)的出现,它允许开发人员将数据存储在浏览器中的 SQL 数据库中,进而允许熟悉 SQL 的开发轻松构建健壮的应用程序。

IndexedDBWebSQL的替代品,提供比以前更多的存储容量。在本文中,我们将探讨如何使用和设置 IndexedDB 进行 Web端的数据存储,以及如何使用 API 操作其数据。

什么是IndexDB

IndexedDB 是用于客户端存储的一种成熟的、持久的 NoSQL 存储系统,可在浏览器中使用,允许存储不同类型的数据,例如:

  • 文件或 Blob
  • 图片和视频
  • 结构化数据,如对象、列表和数组

IndexedDB 可用于各种场景,例如缓存、PWA、游戏等,并且还支持事务。它的开发是为了有效地满足 Web 应用程序的多种需求。

IndexDB的使用

为了更好的展示IndexDB的使用,我们将创建一个基本的 TODO 网页 。

开发一个添加功能以学习如何将数据保存到数据库,另一个功能用于查看所有代办数据,以及一个删除功能。也就是增删改查。

首先我们先创建一个简单的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 APPtitle>
    <script src="index.js" defer>script>
    <style>
    .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;
    }
    style>
  head>
  <body>
    <section>
      <aside class="view">
        <h2>TODOsh2>
        <div class="todos">
          <ol>ol>
        div>
      aside>
      <aside class="add">
        <h2>添加 Todoh2>
        <form>
          <div>
            <label for="title">标题:label>
            <input id="title" type="text" required />
          div>
          <div>
            <label for="desc">描述label>
            <input id="desc" type="text" required />
          div>
          <div>
            <button>保存button>
          div>
        form>
      aside>
    section>
  body>
html>

通过script标签引入核心功能。

创建数据库

首先,我们需要创建数据库;然后,我们可以通过创建一个对象存储(类似于 SQL 中的表)来初始化它,我们将使用它来存储每个项目的详细信息。

let db;

const openOrCreateDB = window.indexedDB.open('todo_db', 1);
openOrCreateDB.addEventListener('error', () =>
  console.error('打开 IndexDB 失败')
);

openOrCreateDB.addEventListener('success', () => {
  console.log('打开 IndexDB 成功');
  db = openOrCreateDB.result;
});

openOrCreateDB.addEventListener('upgradeneeded', (init) => {
  db = init.target.result;

  db.onerror = () => {
    console.error('数据库加载失败');
  };

  const table = db.createObjectStore('todo_tb', {
    keyPath: 'id',
    autoIncrement: true,
  });

  table.createIndex('title', 'title', { unique: false });
  table.createIndex('desc', 'desc', { unique: false });
});

如上所示,创建了一个名为todo_db的数据库,然后创建了一个名为todo_tb的对象存储,其中包含两个索引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'));
}

添加查询功能

要确认保存功能是否有效,可以打开浏览器的检查功能。在 Chrome 浏览器中,可以在“application(应用程序)”选项卡下的“Storage(存储)”中看到 IndexedDB

如下图所示,我们创建了数据库并将第一个待办事项保存到对象存储中:todo_tb
IndexDB完整使用指南_第1张图片

为了在用户加载页面时显示可用的待办事项,并提供以前添加和删除的待办事项的视图,我们将创建一个名为 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);
      }
    }
  });
}

这个方法从存储中获取待办事项,循环遍历为每个事项创建一个li元素,并将元素添加到网页上的列表元素中,并将每个待办事项元素中添加一个data-id(数据库中的唯一ID)属性,用于后续的删除。

把这个方法添加到IndexDB打开成功的监听中:

openOrCreateDB.addEventListener('success', () => {
  console.log('打开 IndexDB 成功');
  db = openOrCreateDB.result;
  showTodos();
});

数据删除

最后添加一个删除功能。

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 删除特定的待办事项,并从网页中删除该元素。删除存储中的最后一个待办事项后,它会在待办事项列表的位置显示“空列表”提示。

要确认待办事项已从数据库中删除,请继续检查网页并单击应用程序选项卡。可以看出,现在不包含任何项目

IndexDB完整使用指南_第2张图片

递增索引数据库版本

IndexedDB 还允许开发人员递增数据库版本。打开数据库时,需要指定所需的版本号。

window.indexedDB.open('todo_db', 1);

如果数据库不存在,则将使用指定的版本创建该数据库。如果数据库已存在,则检查版本号。

如果在 open 方法调用期间指定的版本号高于现有版本,则会通过该事件触发onUpgradeNeeded版本更改事件。此事件允许我们执行数据库架构更改或数据迁移。

这里需要注意的一点是,删除以前的对象存储以添加新选项,创建新存储时也会删除旧存储中的所有其他数据。在升级数据库之前,请注意读出旧内容并将其保存在其他位置。

IndexDB的缺点

数据大小限制

不同的 Web 浏览器对 IndexedDB 中可以存储的最大数据量施加了限制。这些限制因浏览器而异,范围从几m到几百m不等。

不支持DOM操作;不能跨域

你可能感兴趣的:(javascript,前端,javascript)