彌補localStorage容量缺陷方法詳解
正文
localStorage 是前端本地存儲的一種,其容量一般在 5M-10M 左右,用來緩存一些簡單的數(shù)據基本夠用,畢竟定位也不是大數(shù)據量的存儲。
在某些場景下 localStorage 的容量就會有點捉襟見肘,其實瀏覽器是有提供大數(shù)據量的本地存儲的如 IndexedDB 存儲數(shù)據大小一般在 250M 以上。
彌補了localStorage容量的缺陷,但是使用要比localStorage復雜一些 mdn IndexedDB
不過已經有大佬造了輪子封裝了一些調用過程使其使用相對簡單,下面我們一起來看一下
localforage
localforage 擁有類似 localStorage API,它能存儲多種類型的數(shù)據如 Array ArrayBuffer Blob Number Object String,而不僅僅是字符串。
這意味著我們可以直接存 對象、數(shù)組類型的數(shù)據避免了 JSON.stringify 轉換數(shù)據的一些問題。
存儲其他數(shù)據類型時需要轉換成上邊對應的類型,比如vue3中使用 reactive 定義的數(shù)據需要使用toRaw 轉換成原始數(shù)據進行保存, ref 則直接保存 xxx.value 數(shù)據即可。
安裝
下載最新版本 或使用 npm bower 進行安裝使用。
# 引入下載的 localforage 即可使用
<script src="localforage.js"></script>
<script>console.log('localforage is: ', localforage);</script>
# 通過 npm 安裝:
npm install localforage
# 或通過 bower:
bower install localforage
使用
提供了與 localStorage 相同的api,不同的是它是異步的調用返回一個 Promise 對象
localforage.getItem('somekey').then(function(value) {
// 當離線倉庫中的值被載入時,此處代碼運行
console.log(value);
}).catch(function(err) {
// 當出錯時,此處代碼運行
console.log(err);
});
// 回調版本:
localforage.getItem('somekey', function(err, value) {
// 當離線倉庫中的值被載入時,此處代碼運行
console.log(value);
});
提供的方法有
getItem 根據數(shù)據的 key 獲取數(shù)據 差不多返回 null
setItem 根據數(shù)據的 key 設置數(shù)據(存儲undefined時getItem獲取會返回 null)
removeItem 根據key刪除數(shù)據
length 獲取key的數(shù)量
key 根據 key 的索引獲取其名
keys 獲取數(shù)據倉庫中所有的 key。
iterate 迭代數(shù)據倉庫中的所有 value/key 鍵值對。
配置
完整配置可查看文檔 這里說個作者覺得有用的
localforage.config({ name: 'My-localStorage' }); 設置倉庫的名字,不同的名字代表不同的倉庫,當一個應用需要多個本地倉庫隔離數(shù)據的時候就很有用。
const store = localforage.createInstance({
name: "nameHere"
});
const otherStore = localforage.createInstance({
name: "otherName"
});
// 設置某個數(shù)據倉庫 key 的值不會影響到另一個數(shù)據倉庫
store.setItem("key", "value");
otherStore.setItem("key", "value2");
同時也支持刪除倉庫
// 調用時,若不傳參,將刪除當前實例的 “數(shù)據倉庫” 。
localforage.dropInstance().then(function() {
console.log('Dropped the store of the current instance').
});
// 調用時,若參數(shù)為一個指定了 name 和 storeName 屬性的對象,會刪除指定的 “數(shù)據倉庫”。
localforage.dropInstance({
name: "otherName",
storeName: "otherStore"
}).then(function() {
console.log('Dropped otherStore').
});
// 調用時,若參數(shù)為一個僅指定了 name 屬性的對象,將刪除指定的 “數(shù)據庫”(及其所有數(shù)據倉庫)。
localforage.dropInstance({
name: "otherName"
}).then(function() {
console.log('Dropped otherName database').
});
idb-keyval
idb-keyval是用IndexedDB實現(xiàn)的一個超級簡單的基于 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 直接使用即可。
提供的方法
由于其沒有中文的官網,會把例子及自己的理解附上
set 設置數(shù)據
值可以是 數(shù)字、數(shù)組、對象、日期、Blobs等,盡管老Edge不支持null。
鍵可以是數(shù)字、字符串、日期,(IDB也允許這些值的數(shù)組,但IE不支持)。
import { set } from 'idb-keyval';
set('hello', 'world')
.then(() => console.log('It worked!'))
.catch((err) => console.log('It failed!', err));
setMany 設置多個數(shù)據
一個設置多個值,比一個一個的設置更快
import { set, setMany } from 'idb-keyval';
// 不應該:
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ù)據
如果沒有鍵,那么val將返回undefined的。
import { get } from 'idb-keyval';
// logs: "world"
get('hello').then((val) => console.log(val));
getMany 獲取多個數(shù)據
一次獲取多個數(shù)據,比一個一個獲取數(shù)據更快
import { get, getMany } from 'idb-keyval';
// 不應該:
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ù)據
根據 key 刪除數(shù)據
import { del } from 'idb-keyval';
del('hello');
delMany 刪除多個數(shù)據
一次刪除多個鍵,比一個一個刪除要快
import { del, delMany } from 'idb-keyval';
// 不應該:
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 排隊更新數(shù)據,防止由于異步導致數(shù)據更新問題
因為 get 與 set 都是異步的使用他們來更新數(shù)據可能會存在問題如:
// 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 但實際結果是 1,我們可以在第一個回調執(zhí)行第二次操作。
更好的方法是使用 update 來更新數(shù)據
// Instead:
import { update } from 'idb-keyval';
update('counter', (val) => (val || 0) + 1);
update('counter', (val) => (val || 0) + 1);
將自動排隊更新,所以第一次更新將計數(shù)器設置為1,第二次更新將其設置為2。
clear 清除所有數(shù)據
import { clear } from 'idb-keyval';
clear();
entries 返回 [key, value] 形式的數(shù)據
import { entries } from 'idb-keyval';
// logs: [[123, 456], ['hello', 'world']]
entries().then((entries) => console.log(entries));
keys 獲取所有數(shù)據的 key
import { keys } from 'idb-keyval';
// logs: [123, 'hello']
keys().then((keys) => console.log(keys));
values 獲取所有數(shù)據 value
import { values } from 'idb-keyval';
// logs: [456, 'world']
values().then((values) => console.log(values));
createStore 自定義倉庫
文字解釋:表 === store === 商店 一個意思
// 自定義數(shù)據庫名稱及表名稱
// 創(chuàng)建一個數(shù)據庫: 數(shù)據庫名稱為 tang_shi, 表名為 table1
const tang_shi_table1 = idbKeyval.createStore('tang_shi', 'table1')
// 向對應倉庫添加數(shù)據
idbKeyval.set('add', 'table1 的數(shù)據', tang_shi_table1)
// 默認創(chuàng)建的倉庫名稱為 keyval-store 表名為 keyval
idbKeyval.set('add', '默認的數(shù)據')

使用 createStore 創(chuàng)建的數(shù)據庫一個庫只會創(chuàng)建一個表即:
// 同一個庫有不可以有兩個表,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
自己管理定制商店,這個沒搞太明白,看文檔中說既然都用到這個了不如直接使用idb 這個庫
總結
本文介紹了兩個 IndexedDB 的庫,用來解決 localStorage 存儲容量太小的問題
localforage 與 idb-keyval 之間我更喜歡 localforage 因為其與 localStorage 相似的api幾乎沒有上手成本。
如果需要更加靈活的庫可以看一下 dexie.js、PouchDB、idb、JsStore 或者 lovefield 之類的庫
以上就是彌補localStorage容量缺陷方法詳解的詳細內容,更多關于localStorage容量缺陷的資料請關注腳本之家其它相關文章!
相關文章
js解決event.keyCode在Firefox中失效的問題
這篇文章主要介紹了js解決event.keyCode在Firefox中失效的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12
取消Bootstrap的dropdown-menu點擊默認關閉事件方法
今天小編就為大家分享一篇取消Bootstrap的dropdown-menu點擊默認關閉事件方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08
JavaScript Date對象詳解及時間戳和時間的相互轉換問題
這篇文章主要介紹了JavaScript Date對象詳解及時間戳和時間的相互轉換問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2024-01-01

