前言
这次的问题来源于一个简单的需求,要给某个勾选框加上一个月的缓存有效期,即只要选中了这个勾选框,在接下来的一个月内再次进来都会默认勾选上。
什么?这么简单,用缓存记录一下是否勾选的字段,在用缓存存一下当前的时间或者过期的时间,进来的时候判断有没有到时间不就好了吗?
对的,没错,就是这么简单。但是今天做的事就是把这个做成通用一点,你想,假如我们有很多的缓存都想加个有效期,那不可能每一个缓存都去单独给他去另外存一个时间吧,这个有点麻烦,而且有占空间。所以,我们能不能直接在设置缓存的时候就给他加个有效期的参数呢,这样就简单多了
思路
我的项目是用uniapp
搭建的,所有要改写的api是uni.setStorageSync
和uni.getStorageSync
。用原生小程序也是一样的,没什么差别。
首先,先想想看我们希望怎么用最方便,是不是直接在uni.setStorageSync
的最后面补一个时间最方便啊,像这样
uni.setStorageSync('test1', 123, 5000) // 使用相对时间
uni.setStorageSync('test2', 123, '2021/8/1') // 使用绝对时间
实现思路很简单:
在存储缓存的时候,把后面的时间也一并存起来,在读取的时候先比对当前时间与存储的时间,如果过期了,则清空缓存并返回空,没过期则正常返回
那么时间该存在哪呢?
我们可以存储一个对象,对象包含一个expires属性和一个data属性,然后再改写geStorageSync,取值的时候去data里面的值
uni.setStorageSync('test1', 123, 5000)//
//实际存储在缓存中为:{ expires: 5000, data: '123'}
实现
知道原理后代码就很简单了
// 导出后再main.js中引入调用即可
export function uniStorage() {
// 存
const originSetStorageSync = uni.setStorageSync
uni.setStorageSync = function(key, data, expires) {
// 如果没有传第三个有效期参数,就还是用原来的方法
if (!expires) return originSetStorageSync(key, data)
const reg = /\d{4}\/\d{1,12}\/\d{1,31}/ // 这个正则写的比较偷懒,是不够准确的哈哈。用来验证绝对时间格式`yyyy/MM/dd`或者`yyyy/MM/dd hh:mm:ss`
if (reg.test(expires)) { // 绝对日期
const timestamp = new Date(expires + '').getTime()
if (isNaN(timestamp)) {
console.error(expires + ' error 请传入正确的日期格式:yyyy/MM/dd 或者 yyyy/MM/dd hh:mm:ss')
return originSetStorageSync(key, data)
}
originSetStorageSync(key, { data, expires: timestamp })
} else {// 相对日期
if (typeof expires !== 'number') {
console.error('expires is not a number')
return originSetStorageSync(key, data)
}
originSetStorageSync(key, { data, expires: +new Date() + expires })
}
}
// 取
const originGetStorageSymc = uni.getStorageSync
uni.getStorageSync = function(key) {
const data = originGetStorageSymc(key)
// 如果data不是个对象就说明是没加有效期的,直接返回
if (typeof data !== 'object' || (typeof data === 'object' && !data.expires)) return data
const now = +new Date()
if (now < data.expires) {//用当前时间和存储的时间对比
return data.data // 未过期返回data
} else {
// 已过期,移除缓存,返回空
uni.removeStorageSync(key)
return ''
}
}
}
测试使用
uni.setStorageSync('test', 123) //原使用方式,不加有效期
uni.setStorageSync('test1', 123, 5000) // 使用相对时间
uni.setStorageSync('test2', 123, '2021/7/10') // 使用绝对时间
setTimeout(() => {
console.log(uni.getStorageSync('test1')) // 123
}, 3000)
setTimeout(() => {
console.log(uni.getStorageSync('test1')) // '' --已过期
}, 6000)
总结
- 扩写
uni.setStorageSync
api,使其支持第三个参数,绝对时间或者相对时间 - 判断传入的时间是相对还是绝对,再统一转为时间戳,存储一个在对象上,如:{expires: 1627385915263, data:test}
- 改写
uni.geetStorageSync
,取值的时候判断类型是否为对象,是的话再比对当前时间与存储的时间,如果大于存储时间则已过期,情况缓存并返回空,未过期则返回对象的data值
完事~