点击上方'
IT平头哥联盟
'关注与您一起成长~
用心分享 做有温度的攻城狮
引言
这个话题其实在上次分享
已经讲过(
大佬可绕过哦~
),但后来群里/评论都有些同学,提到了一些疑问,问能否单独整理一篇更为详细的分享,讲解一下细节和完善提到的不足,如是有了下文👇。
「
用心分享 做有温度的攻城狮
,我是苏南,让我们一起共同成长。 」
思考点
从我们接触前端起,第一个熟悉的存储相关的Cookie或者来分析我们生活中密切相关的淘宝、物流、闹钟等事物来说起吧,
-
Cookie从你设置的时候,就会给个时间,不设置默认会话结束就过期;
淘宝购物 从你下单付款起,就会给这件货物设置一个收货期限时间,过了这个时间自动认为你收货(即
订单结束
);
-
闹钟 你设置的提醒时间,其实也就是它的过期时间;
-
再比如与您每天切身相关的产品需求,过完需求,你给出的上线时间,也就是这个需求的过期时间;
-
再通俗点讲,您今年的生日过完到明年生日之间也是相当于设置了有效期时间;
以上种种,我们能得出一个结论任何一件事、一个行为动作,都有一个时间、一个节点,甚至我们可以黑
localStorage
,就是一个不完善的API,为什么不能给一个设置过期的机制呢?
sessionStorage
、
Cookie
并不能满足我们实际的需求。
实现思路
抱歉,黑
localStorage
不完善,有点夸张了,综合上述的总结,问题就简单了,给
localStorage
一个过期时间,一切就都so easy ?到底是不是,来看看具体的实现吧:
简单回顾
localStorage.setItem('test',1234567);
let test = localStorage.getItem('test');
console.log(typeof test, test);
localStorage['name'] = '苏南';
console.log(localStorage['name']);
重写 set(存入) 方法:
-
首先有三个参数 key、value、expired ,分别对应 键、值、过期时间,
-
过期时间的单位可以自由发挥,小时、分钟、天都可以,
-
注意
点:存储的值可能是数组/对象,不能直接存储,需要转换
JSON.stringify
,
-
这个时间如何设置呢?在这个值存入的时候在键(key)的基础上扩展一个字段,如:key+'
expires
',而它的值为当前 时间戳 + expired过期时间
-
具体来看一下代码
:
set(key, value, expired) {
let source = this.source;
source[key] = JSON.stringify(value);
if (expired){
source[`${key}__expires__`] = Date.now() + 1000*60*expired
};
return value;
}
重写 get(获取) 方法:
-
获取数据时,先判断之前存储的时间有效期,与当前的时间进行对比;
但存储时
expired
为非必须参数,所以默认为当前时间+1,即长期有效;
-
如果存储时有设置过期时间,且在获取的时候发现已经小于当前时间戳,则执行删除操作,并返回空值;
-
注意
点:存储的值可能是数组/对象,取出后不能直接返回,需要转换
JSON.parse
,
-
具体来看一下代码
:
get(key) {
const source = this.source,
expired = source[`${key}__expires__`]||Date.now+1;
const now = Date.now();
if ( now >= expired ) {
this.remove(key);
return;
}
const value = source[key] ? JSON.parse(source[key]) : source[key];
return value;
}
重写 remove(删除) 方法:
-
删除操作就简单了,直接对
key
进行删除;
remove(key) {
const data = this.source,
value = data[key];
delete data[key];
delete data[`${key}__expires__`];
return value;
}
优化点:
-
记得上次有个
同学
,是这么
评论
的:「 删除缓存能放到constructor里面执行么,放到get里面 不取就一直在那是不是不太好?」;
-
为什么不用
for in
而是 for ?
for in
循环遍历对象的属性时,
原型链
上的所有属性都将被访问,
-
解决方案
:使用
hasOwnProperty
方法过滤或Object.keys会返回自身可枚举属性组成的数组;
class storage {
constructor(props) {
this.props = props || {}
this.source = this.props.source || window.localStorage
this.initRun();
}
initRun(){
const