web-interview icon indicating copy to clipboard operation
web-interview copied to clipboard

[vue] 4. 为什么要替换 Object.defineProperty?

Open qiilee opened this issue 6 years ago • 1 comments

答案:

在 Vue 中,Object.defineProperty 无法监控到数组下标的变化,导致直接通过数组的下标给数组设置值,不能实时响应。

Object.defineProperty 只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。

qiilee avatar Oct 08 '19 05:10 qiilee

其实通过下标给数组设置,是可以触发set方法的,但是像push、shift、unshift等操作数组并不会触发get方法,以下是测试代码

` function myDefineProperty(data, key, value) { Object.defineProperty(data, key, { configurable: true, get: () => { console.log("get", "key:", key); console.log("get", "value:", value); return value; }, set: (newValue) => { console.log("set", "key:", key); console.log("set", "value:", value); console.log("set", "newValue:", newValue); value = newValue; }

        })
    }

    function observe(data) {
        Object.keys(data).forEach((key) => {
            myDefineProperty(data, key, data[key])
        })
    }

    let arr = ['哈哈', '哦哦', '噢噢'];
    observe(arr);

    //通过下标获取数组会触发get方法
    // console.log(arr[0]);

    //通过下标更改数组的值触发set方法
    // arr[0] = '呵呵';

    //通过push增加数组元素,并不能触发get和set方法
    // arr.push("嘻嘻");

    //通过unshift添加数组元素,会导致索引重置,
    //也就是说将所以元素取出来,然后将unshift参数添加到数组中,然后将原来的数组添加到数组,
    //这时候会导致每次添加会触发set方法、get方法(会执行4次)
    // arr.unshift("可可");
    // console.info(arr[arr.length - 1]);//不会触发get方法,这是因为原数组索引为0,1,2的执行了observe,unshift相当于新增了索引,这时候需要手动observe

    //通过pop删除数组元素,会触发get方法
    // arr.pop();

    //删除数组首个元素,会导致数组索引发生变化,会触发set和get方法,最后一个元素需要手动observe(同unshift)
    // arr.shift();

    //从索引为1的位置开始,删除0个元素,并插入"测试"元素,
    //会导致索引发生变化,最后一个元素需要手动observe(同unshift)
    // arr.splice(1, 0, "测试");

`

ChengJunqiang avatar Jan 14 '21 07:01 ChengJunqiang