對(duì)不起 localStorage,現(xiàn)在我愛上 localForage了!
作者: 阿李貝斯前言
https://juejin.cn/post/7275943591410483258
前端本地化存儲(chǔ)算是一個(gè)老生常談的話題了,我們對(duì)于 cookies、Web Storage(sessionStorage、localStorage)的使用已經(jīng)非常熟悉,在面試與實(shí)際操作之中也會(huì)經(jīng)常遇到相關(guān)的問題,但這些本地化存儲(chǔ)的方式還存在一些缺陷,比較明顯的缺點(diǎn)如下:
- 存儲(chǔ)量小:即使是web storage的存儲(chǔ)量最大也只有 5M
- 存取不方便:存入的內(nèi)容會(huì)經(jīng)過序列化,當(dāng)存入非字符串的時(shí)候,取值的時(shí)候需要通過反序列化。
當(dāng)我們的存儲(chǔ)量比較大的時(shí)候,我們一定會(huì)想到我們的 indexedDB,讓我們?cè)跒g覽器中也可以使用數(shù)據(jù)庫這種形式來玩轉(zhuǎn)本地化存儲(chǔ),然而 indexedDB 的使用是比較繁瑣而復(fù)雜的,有一定的學(xué)習(xí)成本,但 localForage 的出現(xiàn)幾乎抹平了這個(gè)缺陷,讓我們輕松無負(fù)擔(dān)的在瀏覽器中使用 indexedDB。
什么是 indexedDB
IndexedDB 是一種底層 API,用于在客戶端存儲(chǔ)大量的結(jié)構(gòu)化數(shù)據(jù)(也包括文件/二進(jìn)制大型對(duì)象)。
存取方便
IndexedDB 是一個(gè)基于 JavaScript 的面向?qū)ο髷?shù)據(jù)庫。IndexedDB 允許你存儲(chǔ)和檢索用鍵索引的對(duì)象;可以存儲(chǔ)結(jié)構(gòu)化克隆算法支持的任何對(duì)象。
之前我們使用 webStorage 存儲(chǔ)對(duì)象或數(shù)組的時(shí)候,還需要先經(jīng)過先序列化為字符串,取值的時(shí)候需要經(jīng)過反序列化,那indexedDB就比較完美的解決了這個(gè)問題,可以輕松存取對(duì)象或數(shù)組等結(jié)構(gòu)化克隆算法支持的任何對(duì)象。
以 stackblitz.com/ 網(wǎng)站為例,我們來看看對(duì)象存到 indexedDB 的表現(xiàn)

異步存取
我相信你肯定會(huì)思考一個(gè)問題:localStorage如果存儲(chǔ)內(nèi)容多的話會(huì)消耗內(nèi)存空間,會(huì)導(dǎo)致頁面變卡。那么 IndexedDB 存儲(chǔ)量過多的話會(huì)導(dǎo)致頁面變卡嗎?
不會(huì)有太大影響,因?yàn)?IndexedDB 的讀取和存儲(chǔ)都是異步的,不會(huì)阻塞瀏覽器進(jìn)程。
龐大的存儲(chǔ)量
IndexedDB 的儲(chǔ)存空間比LocalStorage 大得多,一般可達(dá)到500M,甚至沒有上限。
But.....關(guān)于 indexedDB 的介紹就到此為止,詳細(xì)使用在此不再贅述,因?yàn)楸酒恼挛抑攸c(diǎn)想介紹的是 localForage!
什么是 localForage
localForage 是基于 indexedDB 封裝的庫,通過它我們可以簡(jiǎn)化 IndexedDB 的使用。
兼容性
想必你一定很關(guān)注兼容性問題吧,我們可以看下 localStorage 與 indexedDB 兼容性比對(duì),兩者之間還是有一些小差距。

但是你也不必太過擔(dān)心,因?yàn)?localforage 已經(jīng)幫你消除了這個(gè)心智負(fù)擔(dān),它有一個(gè)優(yōu)雅降級(jí)策略,若瀏覽器不支持 IndexedDB 或 WebSQL,則使用 localStorage。在所有主流瀏覽器中都可用:Chrome,F(xiàn)irefox,IE 和 Safari(包括 Safari Mobile)。
localForage 的使用
- 下載
import localforage from 'localforage'
- 創(chuàng)建一個(gè) indexedDB
const myIndexedDB = localforage.createInstance({
name: 'myIndexedDB',
})
- 存值
myIndexedDB.setItem(key, value)
- 取值
由于indexedDB的存取都是異步的,建議使用 promise.then() 或 async/await 去讀值
myIndexedDB.getItem('somekey').then(function (value) {
// we got our value
}).catch(function (err) {
// we got an error
});
or
try {
const value = await myIndexedDB.getItem('somekey');
// This code runs once the value has been loaded
// from the offline store.
console.log(value);
} catch (err) {
// This code runs if there were any errors.
console.log(err);
}
- 刪除某項(xiàng)
myIndexedDB.removeItem('somekey')
- 重置數(shù)據(jù)庫
myIndexedDB.clear()
細(xì)節(jié)及其他使用方式請(qǐng)參考官方中文文檔 localforage.docschina.org/#localforag…
VUE 推薦使用 Pinia 管理 localForage
如果你想使用多個(gè)數(shù)據(jù)庫,建議通過 pinia 統(tǒng)一管理所有的數(shù)據(jù)庫,這樣數(shù)據(jù)的流向會(huì)更明晰,數(shù)據(jù)庫相關(guān)的操作都寫在 store 中,讓你的數(shù)據(jù)庫更規(guī)范化。
// store/indexedDB.ts
import { defineStore } from 'pinia'
import localforage from 'localforage'
export const useIndexedDBStore = defineStore('indexedDB', {
state: () => ({
filesDB: localforage.createInstance({
name: 'filesDB',
}),
usersDB: localforage.createInstance({
name: 'usersDB',
}),
responseDB: localforage.createInstance({
name: 'responseDB',
}),
}),
actions: {
async setfilesDB(key: string, value: any) {
this.filesDB.setItem(key, value)
},
}
})
我們使用的時(shí)候,就直接調(diào)用 store 中的方法
import { useIndexedDBStore } from '@/store/indexedDB'
const indexedDBStore = useIndexedDBStore()
const file1 = {a: 'hello'}
indexedDBStore.setfilesDB('file1', file1)
前端大學(xué) 公眾號(hào) 祝 您:2023 年暴富!萬事如意! 分享前端干貨,點(diǎn)贊就是最大的支持,
比心??
