最终答案:
1.将缓存localStorage、sessionStorage放在VueX中统一进行维护
2.要对本地缓存做时效处理
3.要对缓存做加密处理
4.根据版本生成缓存键
export const LOCALE_KEY = 'LOCALE__';
// 生成缓存配置,主要包含过期时间、是否加密、根据版本生成缓存键
const createOption = createOptions(localStorage,{TimeOut:24*60*60*7})
const ls = createStorage(createOption);
const lsLocaleSetting = ls.get(LOCALE_KEY) || localeSetting;
export const useLocaleStore = define({
id: 'app-locale',
state: (): LocaleState => ({
// 缓存信息
localInfo: lsLocaleSetting,
}),
getters:{},
actions:{
// 同步修改本地、VueX的缓存信息
setLocaleInfo(info) {
this.localInfo = { ...this.localInfo, ...info };
ls.set(LOCALE_KEY, this.localInfo);
},
// 初始化VueX、本地的缓存信息,这里主要是国际化配置
initLocale() {
this.setLocaleInfo({
...localeSetting,
...this.localInfo,
});
},
}
})
export const localeSetting = {
showPicker: true,
// 地点
locale: LOCALE.ZH_CN,
// 默认语言
fallback: LOCALE.ZH_CN,
// 可用地区
availableLocales: [LOCALE.ZH_CN, LOCALE.EN_US],
};
export const LOCALE = {
ZH_CN: 'zh_CN',
EN_US: 'en',
};
const createOptions = (storage: Storage, options: Options = {}): Options => {
return {
// 开发模式不加密
hasEncrypt: enableStorageEncryption,
storage,
// 根据版本生成缓存键
prefixKey: getStorageShortName(),
...options,
};
};
// 根据当前开发所处的环境判断是否使用aes加密系统缓存
export const enableStorageEncryption = !isDevMode();
// 判断是否处于开发环境
export function isDevMode(): boolean {
return import.meta.env.DEV;
}
// 根据版本生成缓存键,格式为:项目名__所处环境__版本号__
export function getStorageShortName() {
return `${getCommonStoragePrefix()}${`__${pkg.version}`}__`.toUpperCase();
}
export function getCommonStoragePrefix() {
// 从环境中获取项目名
const { VITE_GLOB_APP_SHORT_NAME } = import.meta.env;
// 获取当前环境是开发还是生产并记录
return `${VITE_GLOB_APP_SHORT_NAME}__${import.meta.env.MODE}`.toUpperCase();
}
// key和iv是Aes加密所需的自定义密钥
export const createStorage({
storage = sessionStorage,
key = cacheCipher.key,
iv = cacheCipher.iv,
timeout = null,
hasEncrypt = true,
prefixKey = ''
}: Partial<CreateStorageParams> = {}) => {
// 判断密钥格式是否正确
if (hasEncrypt && [key.length, iv.length].some((item) => item !== 16)) {
throw new Error('When hasEncrypt is true, the key or iv must be 16 bits!');
}
// 创建Aes加密工具
const encryption = new AesEncryption({ key, iv });
// 构造本地缓存实体类
const WebStorage = class WebStorage {
private storage: Storage;
private prefixKey?: string;
private encryption: AesEncryption;
private hasEncrypt: boolean;
constructor() {
this.storage = storage;
this.prefixKey = prefixKey;
this.encryption = encryption;
this.hasEncrypt = hasEncrypt;
}
//prefixKey格式为:项目名__所处环境__版本号__
private getKey(key: string) {
return `${this.prefixKey}${key}`.toUpperCase();
}
// key是缓存键,value是值,expire是过期时间(秒)
set(key: string, value: any, expire: number | null = timeout) {
const stringData = JSON.stringify({
value,
time: Date.now(),
expire: !expire ? new Date().getTime() + expire * 1000 : null,
});
// 是否加密value
const stringifyValue = this.hasEncrypt
? this.encryption.encryptByAES(stringData)
: stringData;
// 设置缓存
this.storage.setItem(this.getKey(key), stringifyValue);
}
get(key: string, def: any = null): any {
const val = this.storage.getItem(this.getKey(key));
if (!val) return def;
try {
// 是否需要解密
const decVal = this.hasEncrypt ? this.encryption.decryptByAES(val) : val;
const data = JSON.parse(decVal);
const { value, expire } = data;
// 判断是否过期
if (isNullOrUnDef(expire) || expire >= new Date().getTime()) {
return value;
}
// 过期则移除
this.remove(key);
} catch (e) {
return def;
}
}
remove(key: string) {
this.storage.removeItem(this.getKey(key));
}
clear(): void {
this.storage.clear();
}
};
return new WebStorage();
};