美文网首页
回顾Vue2,面向Vue3

回顾Vue2,面向Vue3

作者: hellomyshadow | 来源:发表于2020-07-19 16:07 被阅读0次

    Vue2的历史问题

    Object.defineProperty() 是可以监听数组的,key是角标,value是元素值。
    但对数组插入、删除、排序操作时,数据元素的位置会发生移动,造成每个元素的getter、setter频繁调用,严重影响性能!所以,Vue2 放弃使用监听数组!

    function defineReactive(data, key, value) {
        Object.defineProperty(data, key, {
            enumerable: true,
            configurable: true,
            get: function defineGet() {
                return value
            },
            set: function defineSet(newVal) {
                value = newVal
            }
        })
    }
    function observe(data) {
        Object.keys(data).forEach(key => {
            defineReactive(data, key, data[key])
        })
    }
    
    var arr = ['a', 'b', 'c']
    observe(arr)
    

    Object.defineProperty() 的真正问题是:不能对初始化时没有设置的键值做监听!

    var arr = [1, 2, 3]
    observe(arr)
    arr.push(4)  // 无法监听角标为 3,元素值为4 的数组元素
    
    var obj = { name: 'Jscript' }
    observe(obj)
    obj.age = 18  //无法监听 age 属性
    

    这也是为什么会有Vue2要重写数组的方法,并提供 Vue.setAPI
    另外,Object.defineProperty() 需要一开始就初始化递归遍历,循环监听,这也是性能瓶颈之一。

    也正是因为这些历史遗留问题,才会有Vue3

    Vue3 Proxy

    Object.defineProperty() 是重写对象的key,而 Proxy 只是拦截读写操作。

    Vue3采用 懒代理 解决深度嵌套问题,只需要遍历第一层的属性即可!

    function reactive(data) {
        return new Proxy(data, {
            get(target, key, receiver) {
                var res = Reflect.get(target, key, receiver);
                if(typeof ref == 'object') {
                    return reactive(res);   // 懒代理
                }
                return res;
            },
            set(target, key, value, receiver) {
                return Reflect.get(target, key, value, receiver);
            }
        })
    }
    

    对数组做插入、删除、排序操作时,仍然会多次触发 Proxy getter/setter,那么 Vue3 中做了什么优化呢?

    相关文章

      网友评论

          本文标题:回顾Vue2,面向Vue3

          本文链接:https://www.haomeiwen.com/subject/epfrkktx.html