彌補(bǔ)localStorage容量缺陷方法詳解
正文
localStorage
是前端本地存儲的一種,其容量一般在 5M-10M
左右,用來緩存一些簡單的數(shù)據(jù)基本夠用,畢竟定位也不是大數(shù)據(jù)量的存儲。
在某些場景下 localStorage
的容量就會有點(diǎn)捉襟見肘,其實(shí)瀏覽器是有提供大數(shù)據(jù)量的本地存儲的如 IndexedDB
存儲數(shù)據(jù)大小一般在 250M
以上。
彌補(bǔ)了localStorage
容量的缺陷,但是使用要比localStorage
復(fù)雜一些 mdn IndexedDB
不過已經(jīng)有大佬造了輪子封裝了一些調(diào)用過程使其使用相對簡單,下面我們一起來看一下
localforage
localforage 擁有類似 localStorage
API,它能存儲多種類型的數(shù)據(jù)如 Array
ArrayBuffer
Blob
Number
Object
String
,而不僅僅是字符串。
這意味著我們可以直接存 對象、數(shù)組類型的數(shù)據(jù)避免了 JSON.stringify
轉(zhuǎn)換數(shù)據(jù)的一些問題。
存儲其他數(shù)據(jù)類型時(shí)需要轉(zhuǎn)換成上邊對應(yīng)的類型,比如vue3中使用 reactive
定義的數(shù)據(jù)需要使用toRaw
轉(zhuǎn)換成原始數(shù)據(jù)進(jìn)行保存, ref
則直接保存 xxx.value
數(shù)據(jù)即可。
安裝
下載最新版本 或使用 npm
bower
進(jìn)行安裝使用。
# 引入下載的 localforage 即可使用 <script src="localforage.js"></script> <script>console.log('localforage is: ', localforage);</script> # 通過 npm 安裝: npm install localforage # 或通過 bower: bower install localforage
使用
提供了與 localStorage
相同的api,不同的是它是異步的調(diào)用返回一個(gè) Promise
對象
localforage.getItem('somekey').then(function(value) { // 當(dāng)離線倉庫中的值被載入時(shí),此處代碼運(yùn)行 console.log(value); }).catch(function(err) { // 當(dāng)出錯(cuò)時(shí),此處代碼運(yùn)行 console.log(err); }); // 回調(diào)版本: localforage.getItem('somekey', function(err, value) { // 當(dāng)離線倉庫中的值被載入時(shí),此處代碼運(yùn)行 console.log(value); });
提供的方法有
getItem
根據(jù)數(shù)據(jù)的 key
獲取數(shù)據(jù) 差不多返回 null
setItem
根據(jù)數(shù)據(jù)的 key
設(shè)置數(shù)據(jù)(存儲undefined
時(shí)getItem獲取會返回 null
)
removeItem
根據(jù)key刪除數(shù)據(jù)
length
獲取key的數(shù)量
key
根據(jù) key 的索引獲取其名
keys
獲取數(shù)據(jù)倉庫中所有的 key。
iterate
迭代數(shù)據(jù)倉庫中的所有 value/key
鍵值對。
配置
完整配置可查看文檔 這里說個(gè)作者覺得有用的
localforage.config({ name: 'My-localStorage' });
設(shè)置倉庫的名字,不同的名字代表不同的倉庫,當(dāng)一個(gè)應(yīng)用需要多個(gè)本地倉庫隔離數(shù)據(jù)的時(shí)候就很有用。
const store = localforage.createInstance({ name: "nameHere" }); const otherStore = localforage.createInstance({ name: "otherName" }); // 設(shè)置某個(gè)數(shù)據(jù)倉庫 key 的值不會影響到另一個(gè)數(shù)據(jù)倉庫 store.setItem("key", "value"); otherStore.setItem("key", "value2");
同時(shí)也支持刪除倉庫
// 調(diào)用時(shí),若不傳參,將刪除當(dāng)前實(shí)例的 “數(shù)據(jù)倉庫” 。 localforage.dropInstance().then(function() { console.log('Dropped the store of the current instance'). }); // 調(diào)用時(shí),若參數(shù)為一個(gè)指定了 name 和 storeName 屬性的對象,會刪除指定的 “數(shù)據(jù)倉庫”。 localforage.dropInstance({ name: "otherName", storeName: "otherStore" }).then(function() { console.log('Dropped otherStore'). }); // 調(diào)用時(shí),若參數(shù)為一個(gè)僅指定了 name 屬性的對象,將刪除指定的 “數(shù)據(jù)庫”(及其所有數(shù)據(jù)倉庫)。 localforage.dropInstance({ name: "otherName" }).then(function() { console.log('Dropped otherName database'). });
idb-keyval
idb-keyval
是用IndexedDB
實(shí)現(xiàn)的一個(gè)超級簡單的基于 promise
的鍵值存儲。
安裝
npm
npm install idb-keyval
// 全部引入 import idbKeyval from 'idb-keyval'; idbKeyval.set('hello', 'world') .then(() => console.log('It worked!')) .catch((err) => console.log('It failed!', err)); // 按需引入會搖樹 import { get, set } from 'idb-keyval'; set('hello', 'world') .then(() => console.log('It worked!')) .catch((err) => console.log('It failed!', err)); get('hello').then((val) => console.log(val));
瀏覽器直接引入 <script src="https://cdn.jsdelivr.net/npm/idb-keyval@6/dist/umd.js"></script>
暴露的全局變量是 idbKeyval
直接使用即可。
提供的方法
由于其沒有中文的官網(wǎng),會把例子及自己的理解附上
set 設(shè)置數(shù)據(jù)
值可以是 數(shù)字、數(shù)組、對象、日期、Blobs等,盡管老Edge不支持null。
鍵可以是數(shù)字、字符串、日期,(IDB也允許這些值的數(shù)組,但I(xiàn)E不支持)。
import { set } from 'idb-keyval'; set('hello', 'world') .then(() => console.log('It worked!')) .catch((err) => console.log('It failed!', err));
setMany 設(shè)置多個(gè)數(shù)據(jù)
一個(gè)設(shè)置多個(gè)值,比一個(gè)一個(gè)的設(shè)置更快
import { set, setMany } from 'idb-keyval'; // 不應(yīng)該: Promise.all([set(123, 456), set('hello', 'world')]) .then(() => console.log('It worked!')) .catch((err) => console.log('It failed!', err)); // 這樣做更快: setMany([ [123, 456], ['hello', 'world'], ]) .then(() => console.log('It worked!')) .catch((err) => console.log('It failed!', err));
get 獲取數(shù)據(jù)
如果沒有鍵,那么val
將返回undefined
的。
import { get } from 'idb-keyval'; // logs: "world" get('hello').then((val) => console.log(val));
getMany 獲取多個(gè)數(shù)據(jù)
一次獲取多個(gè)數(shù)據(jù),比一個(gè)一個(gè)獲取數(shù)據(jù)更快
import { get, getMany } from 'idb-keyval'; // 不應(yīng)該: Promise.all([get(123), get('hello')]).then(([firstVal, secondVal]) => console.log(firstVal, secondVal), ); // 這樣做更快: getMany([123, 'hello']).then(([firstVal, secondVal]) => console.log(firstVal, secondVal), );
del 刪除數(shù)據(jù)
根據(jù) key
刪除數(shù)據(jù)
import { del } from 'idb-keyval'; del('hello');
delMany 刪除多個(gè)數(shù)據(jù)
一次刪除多個(gè)鍵,比一個(gè)一個(gè)刪除要快
import { del, delMany } from 'idb-keyval'; // 不應(yīng)該: Promise.all([del(123), del('hello')]) .then(() => console.log('It worked!')) .catch((err) => console.log('It failed!', err)); // 這樣做更快: delMany([123, 'hello']) .then(() => console.log('It worked!')) .catch((err) => console.log('It failed!', err));
update 排隊(duì)更新數(shù)據(jù),防止由于異步導(dǎo)致數(shù)據(jù)更新問題
因?yàn)?get
與 set
都是異步的使用他們來更新數(shù)據(jù)可能會存在問題如:
// Don't do this: import { get, set } from 'idb-keyval'; get('counter').then((val) => set('counter', (val || 0) + 1); ); get('counter').then((val) => set('counter', (val || 0) + 1); );
上述代碼我們期望的是 2
但實(shí)際結(jié)果是 1
,我們可以在第一個(gè)回調(diào)執(zhí)行第二次操作。
更好的方法是使用 update
來更新數(shù)據(jù)
// Instead: import { update } from 'idb-keyval'; update('counter', (val) => (val || 0) + 1); update('counter', (val) => (val || 0) + 1);
將自動排隊(duì)更新,所以第一次更新將計(jì)數(shù)器設(shè)置為1
,第二次更新將其設(shè)置為2
。
clear 清除所有數(shù)據(jù)
import { clear } from 'idb-keyval'; clear();
entries 返回 [key, value]
形式的數(shù)據(jù)
import { entries } from 'idb-keyval'; // logs: [[123, 456], ['hello', 'world']] entries().then((entries) => console.log(entries));
keys 獲取所有數(shù)據(jù)的 key
import { keys } from 'idb-keyval'; // logs: [123, 'hello'] keys().then((keys) => console.log(keys));
values 獲取所有數(shù)據(jù) value
import { values } from 'idb-keyval'; // logs: [456, 'world'] values().then((values) => console.log(values));
createStore 自定義倉庫
文字解釋:表 === store === 商店 一個(gè)意思
// 自定義數(shù)據(jù)庫名稱及表名稱 // 創(chuàng)建一個(gè)數(shù)據(jù)庫: 數(shù)據(jù)庫名稱為 tang_shi, 表名為 table1 const tang_shi_table1 = idbKeyval.createStore('tang_shi', 'table1') // 向?qū)?yīng)倉庫添加數(shù)據(jù) idbKeyval.set('add', 'table1 的數(shù)據(jù)', tang_shi_table1) // 默認(rèn)創(chuàng)建的倉庫名稱為 keyval-store 表名為 keyval idbKeyval.set('add', '默認(rèn)的數(shù)據(jù)')
使用 createStore
創(chuàng)建的數(shù)據(jù)庫一個(gè)庫只會創(chuàng)建一個(gè)表即:
// 同一個(gè)庫有不可以有兩個(gè)表,custom-store-2 不會創(chuàng)建成功: const customStore = createStore('custom-db-name', 'custom-store-name'); const customStore2 = createStore('custom-db-name', 'custom-store-2'); // 不同的庫 有相同的表名 這是可以的: const customStore3 = createStore('db3', 'keyval'); const customStore4 = createStore('db4', 'keyval');
promisifyRequest
自己管理定制商店,這個(gè)沒搞太明白,看文檔中說既然都用到這個(gè)了不如直接使用idb 這個(gè)庫
總結(jié)
本文介紹了兩個(gè) IndexedDB
的庫,用來解決 localStorage
存儲容量太小的問題
localforage
與 idb-keyval
之間我更喜歡 localforage
因?yàn)槠渑c localStorage
相似的api幾乎沒有上手成本。
如果需要更加靈活的庫可以看一下 dexie.js、PouchDB、idb、JsStore 或者 lovefield 之類的庫
以上就是彌補(bǔ)localStorage容量缺陷方法詳解的詳細(xì)內(nèi)容,更多關(guān)于localStorage容量缺陷的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript必知必會(三) String .的方法來自何方
這篇文章主要介紹了JavaScript必知必會(三) String .的方法來自何方的相關(guān)資料,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下2016-06-06jquery 實(shí)現(xiàn)上下滾動效果示例代碼
上下滾動的效果,不用說,大家都有看到過,本文為大家介紹下使用jquery實(shí)現(xiàn)上下滾動效果,感興趣的朋友可以參考下,希望對大家有所幫助2013-08-08JavaScript中函數(shù)聲明與函數(shù)表達(dá)式的區(qū)別詳解
可能很多朋友只知道兩種聲明方式一個(gè)是函數(shù)聲明一個(gè)是函數(shù)表達(dá)式,具體有什么不同沒能說得很好。事實(shí)上,JavaScript的解析器對函數(shù)聲明與函數(shù)表達(dá)式并不是一視同仁地對待的。下面看看這兩者到底有什么不同。2016-08-08用js控制組織結(jié)構(gòu)圖可以任意拖拽到指定位置
用js控制生成了一個(gè)組織結(jié)構(gòu)圖并設(shè)置這個(gè)組織結(jié)構(gòu)可以任意拖動到指定位置,具體代碼如下2014-01-01