当前位置: 首页 > 知识库问答 >
问题:

javascript - 手写 useLocalStorage 时发现的问题?

益何平
2023-11-13
/**         * 获取浏览器 localStorage 中的值, 也可对该值进行更新操作         *         * @param {String} key---localStorage中存储的键值对的key         * @return {String} value---localStorage中存储的键值对的value         * @return {Function} setValue---更新方法,可对localStorage中存储的键值对进行更新操作,本方法接受一个参数,该参数为更新后的值         *         * @example         * const { value: nameValue, setValue: setNameValue } = useLocalStorage('name')         * console.log(nameValue)         * setNameValue('uni-app')         * console.log(nameValue)         */        function useLocalStorage(key) {            // 生成一个代理对象            const ref = {}            Object.defineProperty(ref, key, {                get() {                    const storage = JSON.parse(localStorage.getItem(key) ?? '')                    return storage                },            })            function setValue(newVal) {                localStorage.setItem(key, JSON.stringify(newVal))            }            return {                get value() {                    return ref[key]                },                setValue,            }        }        localStorage.setItem('name', JSON.stringify('uni-app'))        const { value: nameValue, setValue: setNameValue } = useLocalStorage('name')        console.log(nameValue) // 'uni-app'        setNameValue('JavaScript')        console.log(nameValue) // 这里输出的不是 'JavaScript', 仍然是 'uni-app'

问题就是代码段最后一个输出,不知道为什么还是 "uni-app"

共有4个答案

邢良才
2023-11-13

我发现修改一下使用方式可以达到目标效果,但会给使用增加麻烦

function useLocalStorage(key) {            // 生成一个代理对象            const ref = {}            Object.defineProperty(ref, 'value', {                get() {                    const storage = JSON.parse(localStorage.getItem(key) ?? '')                    return storage                },            })            function setValue(newVal) {                localStorage.setItem(key, JSON.stringify(newVal))            }            return {                value: ref,                setValue,            }        }        localStorage.setItem('name', JSON.stringify('uni-app'))        const { value: nameValue, setValue: setNameValue } = useLocalStorage('name')        console.log(nameValue.value) // 'uni-app'        setNameValue('JavaScript')        console.log(nameValue.value) // 此时这里输出的就是 'JavaScript'

而且如果解构的话,好像是无法触发 get 的:

const obj = {                count: 1,                get value() {                    return obj.count++                },            }            const { count, value } = obj            console.log(value) // 1            console.log(value) // 1            console.log(obj.value) // 2            console.log(obj.value) // 3
郭元明
2023-11-13
  • 使用 setNameValue('JavaScript') 之后 localStorage 中的指已经变为JavaScript, 但是变量nameValue 还没有改变 需要重新 读取之后 才能变化
  • 末尾再读取一次之后 再输出

      const { value: nameValue, setValue: setNameValue } = useLocalStorage('name')  console.log(nameValue) // 'JavaScript'
韩宜春
2023-11-13
const { value: nameValue, setValue: setNameValue } = useLocalStorage('name')

nameValue是基本类型,而不是引用类型,自然还是'uni-app'

咸利
2023-11-13

这段代码的问题在于,你试图返回一个代理对象,但是你的实现方式并没有正确地创建代理。在你的代码中,你创建了一个对象 ref 并使用 Object.defineProperty 来定义其属性。然而,这并没有创建你想要的代理。

具体来说,Object.defineProperty 是一个静态方法,它不能用来创建动态的代理。你需要使用动态的代理解决方案,比如使用 Proxy 对象。

这是一个更正确的使用 Proxy 来创建代理的例子:

function useLocalStorage(key) {    const initialValue = localStorage.getItem(key) ?? '';    const value = JSON.parse(initialValue || '{}');    return new Proxy({        get(target, prop) {            if (prop === key) {                return value;            }        },        set(target, prop, value) {            if (prop === key) {                localStorage.setItem(key, JSON.stringify(value));                this[prop] = value;            }            return true;        }    });}

在这个例子中,我们使用 Proxy 对象来创建一个代理。这个代理会拦截所有的 getset 操作,并且如果操作的属性名和我们指定的 key 相同,我们就对其进行相应的操作。对于 get 操作,我们直接返回存储的值。对于 set 操作,我们首先将新的值存储到 localStorage 中,然后更新我们的代理对象。这样,无论何时你访问或设置 key 的值,你都是在操作同一个代理对象,而不是直接操作 localStorage。

 类似资料:
  • 本文向大家介绍手写代码:LCS问题相关面试题,主要包含被问及手写代码:LCS问题时的应答技巧和注意事项,需要的朋友参考一下 参考回答: 最长公共子序列代码  

  • 问题内容: 我正在尝试使用PrintStream在Java文件中写入0xFF。当我使用十六进制编辑器打开其他值时,会将其他值正确写入文件,但是假定显示0xFF的值却改为0xC3BF。 使用的变量类型为int。经过几次尝试后,我还发现我可以输入的“最大值”值为0x7F,这将在十六进制编辑器中正确显示,如果我输入0x80,则十六进制编辑器将显示0xC280。 怎么了? 问题答案: 进行一些调查后发现,

  • 本文向大家介绍Android实现手写签名,包括了Android实现手写签名的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了Android手写签名的实现方法,产品要求用户可以在app上签协议。。所以得弄个手写签名版,参考了一些资料自己写了个PaintView去继承View,实现签名功能。 以上就是本文的全部内容,希望对大家的学习有所帮助。

  • 本文向大家介绍使用C# 的webBrowser写模拟器时的javascript脚本调用问题,包括了使用C# 的webBrowser写模拟器时的javascript脚本调用问题的使用技巧和注意事项,需要的朋友参考一下 感觉很久不写模拟器代码了,昨天调试的时候碰了点壁,记录下来,避免大家再跟我犯同样的错误。 加入Javascript脚本的地方: 调用的地方: 大家特别注意的是后面脚本调用的时候,只能出

  • 我正在使用Android Studio,当我在我的手机中构建和安装apk时遇到问题,它给我这个错误:安装失败,消息无效文件:~/项目/应用程序/构建/中间/拆分apk/调试/切片/slices_1.apk如果存在,则可能通过卸载现有版本的apk来解决此问题, ,然后重新安装 附言:我的手机上没有任何版本的apk

  • 我正在开发一个程序,该程序必须重写Comparable中的CompareTo(),以生成集合。排序()工作。因为我使用的是一个由助手组成的ArrayList,我必须根据名称进行排序。 我环顾了论坛,发现了这一点,并尝试改变 到 作为回报,我可以使用这些收藏。sort()在另一个类中,并且没有警告我任何错误,但是,出现了两个新错误。 首先,在同一行中 它告诉我“它不是抽象的,也不会覆盖Compara