首页 - 崮生写笔记的地方

storage事件 + 回调

跨页面传值通讯

mdn storage 文档

最近跨页面传值碰到的越来越多,a页面要刷新b页面,b页面要拿c页面的值之类的,简单的监听storage事件已经不能够满足需求了。

于是对storage事件进行了封装,解决了storage事件的一些弊端

  • 触发写入操作的页面下的storage listener不会被触发
  • 重复设置相同值不会触发listener

未解决的问题

  • safari隐身模式下无法设置localStorage值 由于目前主要用于混合式app开发,基本不会遇上这个问题,所以留待以后解决

完成的一些扩展

  • 可以传递对象
  • 监听器会尝试解析值转成对象
  • 可以传递一个回调函数 (这是看到socket.io 可以传递函数产生的想法,最终实现了,不知道和socket.io的思路是否一致)

ts实现的代码

/*------------[Storage]------------*/
interface onStorageCallback {
    (...args: any[]): void
}
/** 存入的值的接口 */
interface onStorageValue{
    _callback_function_?:Function|string
    /** 用于确保每次都触发事件 */
    _date_now_time_:number
    [key: number]: any
    [key: string]: any
}
/** 取出的值的接口 */
interface onStorageValue2 extends onStorageValue{
    /** 回调函数 */
    _callback_function_:Function
}
interface onStorageEvent{
    key:string,
    oldValue:string,
    newValue: onStorageValue,
    local: boolean
}
let util_onStorage_map = new Map() //存储监听的事件和函数
/**
 * 监听storage事件
 * @param {String} key         要监听的storage key
 * @param {Function} fun    事件处理函数 (e.newValue,e)
 */
export function onStorage(key: string, fun: {(...args: any[]):void}) {
    util_onStorage_map.set(key, fun)
}
/**
 * 触发storage事件
 */
export function triggerStorage(key: string, value:any, callback?: onStorageCallback) {
    let event:onStorageEvent = {
        key,
        oldValue: localStorage.getItem(key),
        newValue: value,
        local: false
    }
    if (typeof value === "object") {
        /** 当前时间戳 */
        value._date_now_time_ = Date.now()// 以便每次都触发
        if (callback) {//存在回调函数
            /** 回调函数监听的key */
            value._callback_function_ = '_callback_' + callback.name + '_' + Date.now()
            /** 上面那个key触发的事件交给 callback */
            onStorage(value._callback_function_,value=>callback(...value))
        }
        localStorage.setItem(key, JSON.stringify(value))
    }else
        localStorage.setItem(key,value)
    if (util_onStorage_map.has(event.key)) { //此页面也有监听storage的函数,因为下面的监听捕获不到故在此处罚
        event.local = true //这个事件是自己这个页面触发的
        handle(event)
    }
}
window.addEventListener("storage", handle)

function handle(e: any) {
    var newValue = e.newValue
    try {/** 尝试序列化 */
        newValue = JSON.parse(e.newValue)
    } catch (e) {
    }
    if (typeof newValue === "object" && newValue._callback_function_ !== undefined) {
        const storageKey = newValue._callback_function_
        /** 传递过来的回调函数 */
        newValue._callback_function_ = function (...value:any) {
            triggerStorage(storageKey, value)
        }
    }
    if (util_onStorage_map.has(e.key)) //将新值传给监听该key的函数
        util_onStorage_map.get(e.key)(newValue, e) //触发监听这个key的函数
}
/*############[Storage]############*/
代码库-git