@ozo/react-rock
Version:
React 移动端开发脚手架,基于CRA3,通用、开箱即用。
103 lines (96 loc) • 3.87 kB
JavaScript
/**
* 用于将需要的数据保存到本地存储,如localStorage等
*/
import { autorun } from 'mobx';
/**
* 检测 storage 是否同时受支持和可用的函数
* @param {*} type storage类型,包括localStorage和sessionStorage
* @returns {boolean}
*/
function storageAvailable(type) {
let storage;
try {
storage = window[type];
const x = '__storage_test__';
storage.setItem(x, x);
storage.removeItem(x);
return true;
} catch (e) {
return (
e instanceof DOMException &&
// everything except Firefox
(e.code === 22 ||
// Firefox
e.code === 1014 ||
// test name field too, because code might not be present
// everything except Firefox
e.name === 'QuotaExceededError' ||
// Firefox
e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&
// acknowledge QuotaExceededError only if there's something already stored
storage &&
storage.length !== 0
);
}
}
/**
* 设置对某个Store下的某个字段进行监听,如果该字段有变化就存储到localStorage
* 注:尽量不要使用Object对象来进行持久化,因为对象中的某个值改变不会触发反应函数。如果必须使用对象,那请使用深拷贝对对象赋值
* @param {String} store Store名
* @param {string} name 字段名
* @param {boolean} inSessionStorage 是否存放到sessionStorage
* @param {boolean} global 是否用于全局,true则存入storage时不携带store名
*/
function persistItem(store, name, inSessionStorage = false, global = false) {
const storage = inSessionStorage ? window.sessionStorage : window.localStorage;
// 避免名称冲突
const keyName = global ? `${name}` : `${store.constructor.name}_${name}`;
const persistedData = storage.getItem(keyName);
// 如果本地已经存在keyName,将数据初始化到store对应的变量上
if (persistedData !== null) {
try {
// 如果为undefined
if ('undefined' === typeof persistedData) {
store[name] = undefined;
} else {
// 如果能转换为对象或,则会自动转换为对象
const tData = JSON.parse(persistedData);
if (['object', 'boolean'].includes(typeof tData)) {
store[name] = tData;
} else {
store[name] = persistedData;
}
}
} catch (error) {
store[name] = persistedData;
}
}
autorun(() => {
let data = store[name];
if (typeof data !== 'undefined' && typeof data !== 'function' && data !== null) {
storage.setItem(keyName, typeof data !== 'string' ? JSON.stringify(data) : data);
} else {
storage.removeItem(keyName);
}
});
}
/**
* @description 数据持久化(localStorage或者sessionStorage)
* @param {String} store Store名
* @param {string|array} keyNames 需要持久化的键值项名称
* @param {boolean} inSessionStorage 是否持久化到sessionStorage
* @param {boolean} global 是否用于全局,true则存入storage时不携带store名
*/
export function persistParam(store, keyNames, inSessionStorage = false, global = false) {
if (!storageAvailable('localStorage') || !storageAvailable('sessionStorage')) {
throw Error('本应用暂不支持隐私/无痕浏览模式,请切换到正常模式使用。');
}
if (!keyNames) {
return;
}
if (typeof keyNames === 'string') {
persistItem(store, keyNames, inSessionStorage, global);
} else {
keyNames.forEach((keyName) => persistItem(store, keyName, inSessionStorage, global));
}
}