cookie,localStorage,sessionStorage和浏览器数据库IndexDB的对比,对浏览器存储进行了通用封装,避免无痕模式下浏览器存储无法使用,导致开发保存数据失败
「这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战」
基础对比
- cookie
- 在同源的http请求中携带,在浏览器和服务器间来回传递
- 数据存储大小一般不能超过4k
- 设置的cookie过期时间之前一直有效
- 在所有同源窗口中都是共享的
- 适用于和服务端的交互,常用于存储身份信息,如authcode
- localStorage
- 持久化本地存储,除非主动删除,否则不会过期
- 存储大小为5M或更大
- 在所有同源窗口中都是共享的
- 适用于长期登陆,判断用户是否已登陆;长期保存数据,可与vuex同步数据
- sessionStorage
- 同一个会话的页面才能访问,会话结束时会被清除,仅在当前浏览器窗口关闭前有效
- 存储大小为5M或更大
- 不在不同的浏览器窗口中共享
- 适合敏感账号一次性登陆
- 浏览器数据库 IndexDB
- 浏览器提供的本地数据库,允许储存大量数据,提供查找接口,还能建立索引
- 键值对储存,操作异步,支持事务
- 存储空间大
无痕限制
问题描述:Safari 开启无痕模式后,localStorage 和 sessionStorage 对象本身是存在的,但对其进行 set 操作会报错。无痕模式下 cookie 是可以使用的。
报错信息:QuotaExceededError(code 为 22,存储空间已用完)。推测浏览器把 storage 的内存先清空,然后再设置最大值为 0导致的
解决方案:对 storage 进行一层封装,定义一个 window 的全局变量进行存储,实现如下所示:
// memoryStorage.js 自定义全局存储
function MemoryStorage() {
this._store = {};
}
MemoryStorage.prototype.setItem = function (key, val) {
this._store[key] = String(val);
};
MemoryStorage.prototype.getItem = function (key) {
return this._store.hasOwnProperty(key) ? this._store[key] : null;
};
MemoryStorage.prototype.removeItem = function (key) {
delete this._store[key];
};
MemoryStorage.prototype.clear = function () {
this._store = {};
};
export default MemoryStorage;
// sessionStorage.js 默认存储
import MemoryStorage from "./memoryStorage";
let sessionStorage;
// 判断默认存储是否能用
if (navigator.cookieEnabled && window.sessionStorage) {
sessionStorage = window.sessionStorage;
} else {
sessionStorage = new MemoryStorage();
}
export default {
set(key, val) {
return sessionStorage.setItem(key, JSON.stringify(val));
},
get(key) {
const val = sessionStorage.getItem(key);
if (val === null) return null;
try {
return JSON.parse(val);
} catch (e) {
sessionStorage.removeItem(key);
return null;
}
},
remove(key) {
return sessionStorage.removeItem(key);
},
clear() {
return sessionStorage.clear();
},
};
参考文档: