vue学习日志(1)数据代理

84 阅读2分钟

vue学习日志(1)数据代理

1、Javascripts中的数据代理:Object.defineProperty

1-1、Object.defineProperty作用

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

1-2、Object.defineProperty的常用属性设置

在默认情况下,通过Object.defineProperty()方法添加的属性值无法遍历(for...in...Objects.keys()等方法)、修改(immutable)或者删除(delete)。但Object.defineProperty()方法允许精确地添加或修改对象的属性,以下案例将具体展示各个特性的修改方式。
<script>
    let number = 18
    let person = {
        name: 'john',
        sex: 'man',
        // age: 18 //对象中定义的原生属性可遍历、可修改、可删除
    }
    //Object.defineProperty()方法生成的属性在默认情况下不可遍历,不可修改,不可删除
    Object.defineProperty(person, 'age', {
        // value: 18,
        // enumerable: true, //赋予可遍历特性,默认为false
        // writable: true, //赋予可修改特性,默认为false
        // configurable: true, //赋予可删除特性,默认为false
        //读取person的age属性时,get函数就会被调用,返回值就是age的值
        get: function () {
            return number
        },
        //读取person的age属性时,set函数就会被调用,收到修改的值
        set(value) {
            console.log('age have been changed')
            number = value;
        }
    })
</script>

1-3、Object.defineProperty的数据代理案例

案例中,定义了obj和obj2两个对象,基于Object.defineProperty方法,可以通过obj2获取、修改obj中的属性。
<script>
    let obj = { x: 100 }
    let obj2 = { y: 200 }
    Object.defineProperty(obj2, 'x', {
        get() {
            return obj.x
        },
        set(value) {
            obj.x = value
        }
    })
</script>

image.png

2、数据代理在vue中的体现

通过以下代码可以看出,当修改vue模板的name属性时,vue._data中的name属性也相应发生改变。我们并没有直接修改vue._data中的name值,可见其中发生了数据代理的修改过程(setter函数)。
<body>
    <div id="root">
        <h2>Name:{{name}}</h2>
        <h2>Location{{address}}</h2>
    </div>
</body>

<script>
    Vue.config.productionTip = false;

    const vm = new Vue({
        el: '#root',
        data: {
            name: 'john',
            address: 'Chicago'
        }
    })
</script>

image.png

观察vm属性发现,确实存在类似于Object.defineProperty方法的数据代理过程存在,分别为address和name属性。

image.png

3、vue模型下的数据代理关系

通过简单梳理vue模型的运作流程,我们可以发现vm._data与vm本身的属性之间存在数据代理(也称数据劫持)关系,这一步操作主要是为了在vue模板中更加方便的调用属性。假设vm中没有name属性,或者vm._data中不存在复杂的get和set方法,我们仅能在模板中通过{{_data.name}}调用,这显然更麻烦。同样的,当我们写语句 vm.xxx的时候(而不是vm._data.xxx),就会去调用到get方法,当我们给vm.xxx赋值的时候,就会去调用set方法。

无标题.png

参考网站:

1、MDN官网:Object.defineProperty()简介
2、视频:vue中的数据代理