前端项目中经常使用到localstorage本地存储数据,有时候想监听某个值改变然后使用最新值进行业务操作,而不想每次手动处理这些步骤,可以监听值变化的模式进行统一处理。
一、使用发布订阅模式集中管理值
- events:对象,里面的键代表值名称,值是一个包含很多订阅方法数组。
- release:每当某个值改变,找到events中对应的值,循环执行数组中的订阅方法。
- subscribe:订阅的方法,想监听某个值变化,调用方法并传入键名和订阅回调函数,在回调函数中拿到最新值。
- clear:主要是配置Localstorage.clear()清除所有值。
scss
listerer.ts
const publishSubscription = () => {
const events:{[key:string]:Function[]} = {}
function release (name:string,param:any){
if(events[name]){
events[name].forEach((fn)=>{
fn(param)
})
}
}
function subscribe (name:string,fn:Function) {
if(!events[name]){
events[name] = []
}
events[name].push(fn)
}
function clear () {
const keys = Reflect.ownKeys(events)
if(keys.length){
for(let key in events){
if(Object.hasOwnProperty.call(events,key)){
events[key].forEach((fn)=>{
fn(null)
})
}
}
}
}
return {
release,
subscribe,
clear
}
}
export default publishSubscription()
二、改造Localstorage的相关方法
不直接调Localstorage的api,使用包装后的方法,以便进行发布订阅操作。
- setItem:每次设置值时,就循环执行events中改键对象的数组中的方法。
- 通过subscribe订阅了该键的地方,就会在回调函数中拿到最新的值。
typescript
import PublishSubscription from "./publishSubscription";
const AhjetStorage = {
setItem: (key: string, value: any) => {
localStorage.setItem(key, JSON.stringify(value))
PublishSubscription.release(key,value)
},
getItem: (key: string) => {
return JSON.parse(localStorage.getItem(key) || 'null')
},
removeItem: (key: string) => {
localStorage.removeItem(key)
PublishSubscription.release(key,null)
},
clear: () => {
localStorage.clear()
PublishSubscription.clear()
},
}
export default AhjetStorage
三、效果
typescript
const [user,setUser] = useState('默认值')
const setLocal = () => {
AhjetStorage.setItem("name","ahjet")
}
useEffect(() => {
return PublishSubscription.subscribe('name',(val:any)=>{
setUser(val)
})
}, [])
设置值后,在回调中拿到最新值,再进行对应操作。