一、localStorage与sessionStorage的比较
1、不同点:
1-1、localStorage
没有过期时间设置,可以长期保留
相同浏览器的不同窗口,数据可以共享
限制大小为5M
1-2、sessionStorage
关闭浏览器或窗口,数据会被清除
相同浏览器的相同的URL的多个窗口,数据相互隔离
在浏览器打开期间一直保持,并且重新加载或恢复页面仍会保持原来的数据
通过window.open或链接打开新页面时,新页面能获取上一个页面的数据
2、相同点:
不同浏览器之间的数据相互隔离
不同协议(http与https)+主机名+端口之间的数据相互隔离
无痕/安全模式下启动浏览器和正常启动浏览器之间的数据相互隔离
二、localStorage与sessionStorage的封装
import aes from 'crypto-js/aes';
import utf8Enc from 'crypto-js/enc-utf8';
const PREFIX = '___cache__';
//GUID:全球唯一标识符
function guid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
const r = Math.random() * 16 | 0;
const v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
function getSid() {
const sid = localStorage.getItem('__sid');
if (sid) return sid;
const id = guid();
localStorage.setItem('__sid', id);
return id;
}
function removeSid() {
localStorage.removeItem('__sid');
}
function _Store(store: Storage) {
return class S {
//生成加密需要的key和iv
private static getKV() {
const id = getSid();
const s = id.replace(/-/g, '').split('').reverse().join('');
return { key: s.substring(0, 16), iv: s.substring(16, id.length) }
}
//加密(crypto-js库加密)--如果是非生产环境,不加密
private static encrypt(data: string) {
if (process.env.NODE_ENV !== 'production') return data;
const { key, iv } = this.getKV();
//加密
return aes.encrypt(utf8Enc.parse(data), key, { iv: iv as any }).toString();
}
//解密--如果是非生产环境,不加密
private static decrypt(data: string) {
if (process.env.NODE_ENV !== 'production') return data;
try {
const { key, iv } = this.getKV();
//解密
const rs = aes.decrypt(data, key, { iv: iv as any });
return utf8Enc.stringify(rs);
} catch (e) {
return null
}
}
private static encryptKey(key: string) {
return `${PREFIX}${key}`;
}
public static getItem(k: string) {
try {
const key = this.encryptKey(k);
const value = this.decrypt(store.getItem(key) as string) ;
return JSON.parse(value as string).data;
} catch (e) {
return null;
}
}
public static getDefaultValue<T>(k: string, value: T): T {
const v = S.getItem(k);
return v === null ? value : v;
}
public static setItem<T>(k: string, v: T) {
const key = this.encryptKey(k);
const d = JSON.stringify({ data: v });
store.setItem(key, this.encrypt(d));
}
public static removeItem(k: string) {
const key = this.encryptKey(k);
store.removeItem(key);
}
public static clear() {
Object.keys(store).filter((i: string) => i.startsWith(PREFIX)).forEach((j) => store.removeItem(j));
removeSid();
}
};
}
export const CacheStore = _Store(localStorage);
export const CacheSession = _Store(sessionStorage);
三、浏览器多个tab页中共享sessionStorage
实现思路:监听storage事件,把值放在localStorage中传递,一定要调用removeItem清除
参考:
四、跨浏览器tab页通信
实现思路:HTML5的window.postMessage和监听storage事件来实现
参考:
五、注意
localStorage或者sessionStorage的值发生变化时,storage事件才会触发。如果是相同的值,storage事件不会触发
storage事件只能在不同的tab页能监听到,在同一个tab页监听事件不会触发,例如:tab的A页面localStorage或者sessionStorage的值发生变化,在另一个tab的B页面才会触发storage事件