尝试简化一下window.localStorage的使用方式

71 阅读3分钟

为什么会有上面的这个想法呢?
  1、我在公司的wx小程序项目中开到之前的前端小姐姐自己封装的storage,下图

image.png 前几次用的时候,我还是蛮顺手的,用了特别多次数之后,我就在想为什么我每次都需要xxx.get(),就不能直接xxx进行获取数据吗?正好这几天我在开发自己的工具插件,于是就想着也实现一下这种功能。
  2、我个人主要从事web端开发,编写的插件也是web端的,在web端wx.getStorageSync的平替为window.localStorage,上述的两种原因演变出来了本文的标题。

最初的版本


{
    const storage_get = (name) => JSON.parse(window.localStorage.getItem(name))
    const storage_set = (name, val) => window.localStorage.getItem(name, JSON.stringify(val))
}


这个真没开玩笑,我最初的版本真是这样的,每次用的时候只需要storage_get(xxx)、storage_set(xxx)就行了,我当初还特意加了JSON.stringify、parse来减少使用时的步骤。直到某天半夜,我爬了起来,给了自己两巴掌,**,这样用和xxx.get()有什么区别?这不就是换了个壳子? 于是我趁着周末写了第二个版本。

2.0

在写第二个版本的时候我就在想如果能window.localStorage.xxx直接获取xxx数据,或者window.localStorage.xxx="a"能够直接设置数据不就是方便很多了?出于这种思想下,我编写了2.0


   const init = (arr = []) => {
        const _get = (val) => JSON.parse(window.localStorage.getItem(val))
        const _set = (key, val) => window.localStorage.setItem(key, JSON.stringify(val))
        // 代理的内容
        let STORAGE = {}
        //name的合集
        let key_list = []
        arr.forEach(item => {
            if (typeof (item) == 'string') {
                key_list.push(item)
                STORAGE[item] = item
            }
        })

        const storage = new Proxy(STORAGE, {
            get(target, key) {
                if (key === '$') {
                    return _set
                } else {
                    return _get(key)
                }
            },
            set(target, key, val) {
                if (key_list.includes(key)) {
                    _set(key, val)
                    return true
                } else {
                    return false
                }
            }
        })
        //请各位忽略掉我代码中的'',正常情况我都是用""包裹字符串的
       return storage
    }    

2.0版本的使用方法

//....
//👆引入js文件
  const arr = ['token', 'userinfo']
  const storage = init(arr)
  storage.userinfo = { id: 173, name: 'tjq', time: '1234' } //更新window.localStorage的数据
  //或者  storage.$('userinfo',{name:'tjq'})
  console.log(storage.userinfo); //{ id: 173, name: 'tjq', time: '1234777' }

说真的,到这里我真的以为结束了,我已经认为我就是万中无一的前端天才了,我怀着强烈的自豪感去在我的个人项目中使用时,结果天塌了。

2.1版本

为什么说2.0版本是天塌了?因为我压根没有考虑场景,而是一味的散发我的个人魅力(代码的魅力,另外本人183)

1、我没有考虑到默认值问题(我在使用token时有个习惯,如果是测试环境,token写死,用默认值,生产环境才会调取后端接口)
2、时效性(我个人项目的用户token是有时效性的,前端/后端都有,用了我这个2.0版本,我之前写的失效功能就没用了)
....

看到上述的两个问题,我不由头大,因为其它类似的问题肯定还有很多很多,只是我暂时没有遇到,怀揣着悲伤的情绪我编写了2.1版本(增加了默认值功能,时效性我还在想)


const useStorage = (data) => {
    const arr = data
    /**
    const arr = [
        {
            // 本地存储的名称
            name: "userinfo",
            //描述信息,最好要有
            desc: "存储用户信息",
            // 日后可扩展功能:时效性
            time: 7 * 1000,
            //初始值
            value: "初始值",
        }
    ]
    // 或者 ↓
    const arr = ['userinfo']
    */
    const _get = (val) => JSON.parse(window.localStorage.getItem(val))
    const _set = (key, val) => window.localStorage.setItem(key, JSON.stringify(val))
    // 代理的内容
    let STORAGE = {}
    //name的合集
    let key_list = []
    arr.forEach(item => {
        if (item instanceof Object) {
            let { name, desc = false, value ,time} = item
            if (desc == false) {
                console.warn("您尚未编写注释来介绍" + name + "的作用")
            }
            if (value) {
                _set(name,value)
            }
         
            key_list.push(name)
            STORAGE[name] = {
                ...item
            }

        } else if (typeof (item) == 'string') {
            key_list.push(item)
            STORAGE[item] = item
        }


    })

    const storage = new Proxy(STORAGE, {
        get(target, key) {
            if (key === '$') {
                return _set
            } else {
                return _get(key)
            }
        },
        set(target, key, val) {
            if (key_list.includes(key)) {
                _set(key, val)
                return true
            } else {
                return false
            }
        }
    })
    return storage
}

//...
//👆引入文件
const storage = useStorage([{
name:"token",
value:"默认的token",
desc:"存储token"
}])
export default storage