全文:https://blog.logrocket.com/dexie-js-indexeddb-react-apps-offline-data-storage/
创作者:Ebenezer Don
线下储存应用软件数据信息已变成当代 Web 开发设计中的必备条件。内嵌的电脑浏览器 localStorage 能够作为简易轻巧数据信息的数据储存,可是在非结构化数据或储存很多数据信息层面却不够。
最重要的是,大家只有将字符串数组数据储存在受 XSS 进攻的 localStorage 中,而且它沒有出示许多 查看数据信息的作用。
这就是 IndexedDB 的闪光点。应用 IndexedDB,我们可以在电脑浏览器中建立结构型的数据库查询,将基本上全部內容储存在这种数据库查询中,并对数据信息实行多种类型的查看。
在文中中,大家将掌握 IndexedDB 的所有含意,及其怎么使用 Dexie.js(用以 IndexedDB 的简洁包裝)解决 Web 应用软件中的线下数据储存。
IndexedDB 是用以电脑浏览器的内嵌非关系型数据库。它使开发者可以将数据信息长久储存在电脑浏览器中,即便在离线时还可以无缝拼接应用 Web 应用软件。应用 IndexedDB 时,您会常常见到2个专业术语:数据库查询储存和阿里云oss。使我们在下面开展讨论。
IndexedDB 数据库查询对每一个 Web 应用软件而言全是唯一的。这代表着一个应用软件只有从与自身运作在同一域或子域名的 IndexedDB 数据库查询中浏览数据信息。数据库查询是容下阿里云oss的地区,而阿里云oss又包括储存的数据信息。要应用 IndexedDB 数据库查询,大家必须开启(或联接到)他们:
- const initializeDb = indexedDB.open(
- "name_of_database",
- version
- );
indexedDb.open() 方式中的 name_of_database 主要参数将作为已经建立的数据库查询的名字,而 version 主要参数是一个意味着数据库查询版本号的数据。
在 IndexedDB 中,大家应用阿里云oss来搭建数据库查询的构造,而且每每要升级数据库查询构造时,都必须将版本更新到高些的值。这代表着,如果我们从版本号 1 逐渐,则下一次要升级数据库查询的构造时,大家必须将 indexedDb.open() 方式中的版本号更改成 2 或高些版本号。
阿里云oss类似关系型数据库(如 PostgreSQL)中的表和文本文档数据库查询(如 MongoDB)中的结合。要在 IndexedDB 中创建对象储存,大家必须从以前申明的 initializeDb 自变量中启用 onupgradeneeded() 方式:
- initializeDb.onupgradeneeded = () => {
- const database = initializeDb.result;
- database.createObjectStore("name_of_object_store", {
- autoIncrement: true,
- });
- };
在上面的代码块中,大家从 initializeDb.result 特性获得数据库查询,随后应用其 createObjectStore() 方式创建对象储存。第二个主要参数 {autoIncrement:true} 告知 IndexedDB 全自动出示/提升阿里云oss中新项目的 ID。
我省去了例如事务管理和游标这类的别的专业术语,由于应用低等 IndexedDB API 必须开展很多工作中。这就是为何大家必须 Dexie.js,它是 IndexedDB 的简洁包裝。使我们看一下 Dexie 怎样简单化建立数据库,阿里云oss,储存数据信息及其从数据库数据信息的全部全过程。
应用 Dexie,建立 IndexedDB 数据库查询和阿里云oss很容易:
- const db = new Dexie("exampleDatabase");
- db.version(1).stores({
- name_of_object_store: " id, name, price",
- name_of_another_object_store: " id, title",
- });
在上面的代码块中,大家建立了一个名叫 exampleDatabase 的新数据库查询,并将其做为值分派给 db 自变量。大家应用 db.version(version_number).stores() 方式为数据库查询创建对象储存。每一个阿里云oss的值意味着了它的构造。比如,当在第一个阿里云oss中储存数据信息时,大家必须出示一个具备特性 name 和 price 的目标。 id 选择项的功效如同我们在创建对象储存区的时候应用的 {autoIncrement:true} 主要参数一样。
一定要注意,在大家的应用软件中应用 dexie 包以前,大家必须安裝并导进它。在我们逐渐搭建大家的演试新项目时,大家将见到怎样保证这一点。
针对大家的演试新项目,大家将应用 Dexie.js 和 React 搭建一个销售市场目录应用软件。大家的客户将可以在销售市场目录中加上她们准备选购的产品,删掉这种产品或将其标识为已选购。
大家将见到怎么使用 Dexie useLiveQuery hook 来监控 IndexedDB 数据库查询中的变更及其在数据库查询升级时再次展现 React 部件。它是大家的应用软件的外型:
最先,大家将应用为应用软件的构造和设计方案建立的 GitHub 模版。这儿有一个模版的连接。点一下**Use this template(应用此模版)**按键,便会用目前的模版给你建立一个新的资料库,随后你也就能够复制和应用这一模版。
或是,在计算机上安装了GitHub CLI的状况下,您能够运作下列指令从销售市场目录 GitHub 模版建立名叫 market-list-app 的储存库:
- gh repo create market-list-app --template ebenezerdon/market-list-template
进行此实际操作后,您能够再次在文本编辑器中复制并开启您的新应用软件。应用终端设备在应用软件文件目录中运作下列指令应安裝 npm 依靠项并运行新应用软件:
- npm install && npm start
导航栏到取得成功信息中的当地 URL(一般为http://localhost:3000)时,您应当可以见到新的React应用软件。您的新运用应以下所显示:
当您开启 ./src/App.js 文档时,您会注意到大家的应用软件部件仅包括销售市场目录应用软件的 JSX 编码。大家已经应用Materialize 架构中的类开展款式设定,并将其 CDN 连接包括在 ./public/index.html 文档中。下面,大家将见到怎么使用 Dexie 建立和管理方法数据信息。
要在大家的 React 应用软件中应用 Dexie.js 开展线下储存,大家将从在终端设备中运作下列指令逐渐,以安裝 dexie 和 dexie-react-hooks 程序包:
- npm i -s dexie dexie-react-hooks
大家将应用 dexie-react-hooks 库中的 useLiveQuery hook 来监控变更,并在对 IndexedDB 数据库查询开展升级时再次3D渲染大家的 React 部件。
使我们将下列导进句子加上到大家的 ./src/App.js 文档中。这将导进 Dexie 和 useLiveQuery hook:
- import Dexie from "dexie";
- import { useLiveQuery } from "dexie-react-hooks";
下面,大家将建立一个名叫 MarketList 的新数据库查询,随后申明大家的阿里云oss items:
- const db = new Dexie("MarketList");
- db.version(1).stores({
- items: " id,name,price,itemHasBeenPurchased",
- });
大家的 items 阿里云oss将希望一个具备特性name、price和 itemHasBeenPurchased 的目标,而 id 将由 Dexie 出示。在将新数据加上到阿里云oss里时,大家将为 itemHasBeenPurchased 特性应用默认设置布尔值 false,随后在大家从销售市场明细中购买商品时将其升级为 true。
使我们建立一个自变量来储存大家全部的新项目。大家将应用 useLiveQuery 勾子从 items 阿里云oss中读取数据,并观查在其中的转变 ,那样当 items 阿里云oss有升级时,大家的 allItems 自变量将被升级,大家的部件将用新的数据信息再次3D渲染。大家将在 App 部件內部开展:
- const App = () => {
- const allItems = useLiveQuery(() => db.items.toArray(), []);
- if (!allItems) return null
- ...
- }
在上面的代码块中,大家建立了一个名叫 allItems 的自变量,并将 useLiveQuery 勾子做为其值。useLiveQuery 勾子的英语的语法类似 React 的 useEffect 勾子,它期待一个涵数以及依靠项二维数组做为主要参数。大家的函数调用回到数据库。
在这儿,大家以二维数组文件格式获得 items 阿里云oss中的全部数据信息。在下一行中,大家应用一个标准来告知大家的部件,假如 allItems 自变量是 undefined,则代表着查看仍在加载中。
仍在 App 部件中,使我们建立一个名叫 addItemToDb 的涵数,大家将应用该涵数向数据库查询中加上新项目。每每大家点一下“ADD ITEM(加上新项目)”按键时,大家都是会启用此涵数。请记牢,每一次升级数据库查询时,大家的部件都是会再次3D渲染。
- ...
- const addItemToDb = async event => {
- event.preventDefault()
- const name = document.querySelector('.item-name').value
- const price = document.querySelector('.item-price').value
- await db.items.add({
- name,
- price: Number(price),
- itemHasBeenPurchased: false
- })
- }
- ...
在 addItemToDb 涵数中,大家从表格键入字段名中获得产品名称和价钱值,随后应用 db.[name_of_object_store].add 方式将新产品数据信息加上到产品阿里云oss中。大家还将 itemHasBeenPurchased 特性的初始值设定为 false。
如今大家拥有 addItemToDb 涵数,使我们建立一个名叫 removeItemFromDb 的涵数以从大家的产品阿里云oss中删掉数据信息:
- ...
- const removeItemFromDb = async id => {
- await db.items.delete(id)
- }
- ...
下面,大家将建立一个名叫 markAsPurchased 的涵数,用以将产品标识为已选购。大家的涵数在启用时,会将物件的主键做为第一个主要参数——在本例中是 id,它将应用这一主键来查看大家要想标识为选购的物件的数据库查询。获得产品后,它将其 markAsPurchased 特性升级为 true:
- ...
- const markAsPurchased = async (id, event) => {
- if (event.target.checked) {
- await db.items.update(id, {itemHasBeenPurchased: true})
- }
- else {
- await db.items.update(id, {itemHasBeenPurchased: false})
- }
- }
- ...
在 markAsPurchased 涵数中,大家应用 event 主要参数来获得客户点击的特殊键入原素。假如选定其值,大家将itemHasBeenPurchased 特性升级为 true,不然升级为 false。db.[name_of_object_store] .update() 方式期待此项目地主键做为其第一个主要参数,而新目标数据信息做为其第二个主要参数。
下边是大家的 App 部件在这个环节应当是什么样子。
- ...
- const App = () => {
- const allItems = useLiveQuery(() => db.items.toArray(), []);
- if (!allItems) return null
- const addItemToDb = async event => {
- event.preventDefault()
- const name = document.querySelector('.item-name').value
- const price = document.querySelector('.item-price').value
- await db.items.add({ name, price, itemHasBeenPurchased: false })
- }
- const removeItemFromDb = async id => {
- await db.items.delete(id)
- }
- const markAsPurchased = async (id, event) => {
- if (event.target.checked) {
- await db.items.update(id, {itemHasBeenPurchased: true})
- }
- else {
- await db.items.update(id, {itemHasBeenPurchased: false})
- }
- }
- ...
- }
如今,大家建立一个名叫 itemData 的自变量,以容下大家全部产品数据信息的 JSX 编码:
- ...
- const itemData = allItems.map(({ id, name, price, itemHasBeenPurchased }) => (
- <div className="row" key={id}>
- <p className="col s5">
- <label>
- <input
- type="checkbox"
- checked={itemHasBeenPurchased}
- onChange={event => markAsPurchased(id, event)}
- />
- <span className="black-text">{name}</span>
- </label>
- </p>
- <p className="col s5">${price}</p>
- <i onClick={() => removeItemFromDb(id)} className="col s2 material-icons delete-button">
- delete
- </i>
- </div>
- ))
- ...
在 itemData 自变量中,大家投射了 allItems 数据信息二维数组中的全部新项目,随后从每一个 item 目标获得特性 id、name、price 和 itemHasBeenPurchased。随后,大家再次开展实际操作,并且用数据库查询中的最新消息值更换了之前的数据格式。
留意,大家还应用了 markAsPurchased 和 removeItemFromDb 方式做为相对按键的点击事情侦听器。大家将在下一个代码块里将 addItemToDb 方式加上到表格的 onSubmit 事情中。
准备好 itemData 后,使我们将 App 部件的 return 句子升级为下列 JSX 编码:
- ...
- return (
- <div className="container">
- <h3 className="green-text center-align">Market List App</h3>
- <form className="add-item-form" onSubmit={event => addItemToDb(event)} >
- <input type="text" className="item-name" placeholder="Name of item" required/>
- <input type="number" step=".01" className="item-price" placeholder="Price in USD" required/>
- <button type="submit" className="waves-effect waves-light btn right">Add item</button>
- </form>
- {allItems.length > 0 &&
- <div className="card white darken-1">
- <div className="card-content">
- <form action="#">
- { itemData }
- </form>
- </div>
- </div>
- }
- </div>
- )
- ...
在 return 句子中,大家已将 itemData 自变量加上到大家的新项目目录中(items list)。大家还应用 addItemToDb 方式做为 add-item-form 的 onsubmit 值。
为了更好地检测大家的应用软件,我们可以回到到大家此前开启的 React 网页页面。请记牢,您的 React 运用务必已经运作,要不是,请在终端设备上运行指令 npm start。您的运用应当可以像下边的演试一样运作:
大家还能够应用标准用 Dexie 查看大家的 IndexedDB 数据库查询。比如,假如我们要获得价钱高过 10 美金的全部产品,则能够实行下列实际操作:
- const items = await db.friends
- .where("price")
- .above(10)
- .toArray();
您能够在Dexie 文本文档中查询别的如何查询。
在文中中,大家学了怎么使用 IndexedDB 开展线下储存及其 Dexie.js 怎样简单化该全过程。大家还了解了怎么使用 Dexie useLiveQuery 勾子来监控变更并在每一次升级数据库查询时再次3D渲染 React 部件。
因为 IndexedDB 是电脑浏览器原生态的,从数据库查询中查看和查找数据信息比每一次必须在运用中解决数据信息时都需要推送服务端 API 要求要快得多,并且大家基本上能够在 IndexedDB 数据库查询中储存任何东西。
以往应用 IndexedDB 很有可能对电脑浏览器的适用是一个问题,可是如今全部主流浏览器都适用它。在 Web 运用中应用 IndexedDB 开展线下储存的众多优点超过缺点,将 Dexie.js 与 IndexedDB 一起应用,促使 Web 开发设计越来越史无前例的有意思。
它是大家的演试应用软件的GitHub库的连接。