2.21 Vue2实现双向数据绑定的原理

105 阅读2分钟

Vue2实现双向数据绑定的原理是Object.defineProperty的setter和getter属性

下面以劫持对象为例

Object.defineProperty有三个参数分别是要劫持的对象,要劫持的属性,和一个选项对象

选项对象里有

valueVue2实现双向数据绑定的原理是Object.defineProperty的setter和getter属性

下面以劫持对象为例

Object.defineProperty有三个参数分别是要劫持的对象,要劫持的属性,和一个选项对象

选项对象里有

  • value 值 当有get和set时不可用,否则报错
  • writable 可写 值为true和false 当有get和set时不可用,否则报错
  • enumerable 可读 值为true和false
  • configurable: false, 可以删除吗

Object.defineProperty(obj, 'name', {
    value: "张三", // 值 当有get和set时不可用,否则报错
    writable: false, // 可写也就是可以改变吗 当有get和set时不可用,否则报错
    enumerable: true, // 可读也就是可以进行访问吗
    configurable: false, // 可以删除吗

})

还有两个方法

  • set 读取属性时调用
  • get 设置属性时调用
Object.defineProperty(obj, 'name', {
    // value: "张三", // 值 当有get和set时不可用,否则报错
    // writable: false, // 可写也就是可以改变吗 当有get和set时不可用,否则报错
    enumerable: true, // 可读也就是可以进行访问吗
    configurable: false, // 可以删除吗

    get() { // 读取属性时调用
        return '我是' + objName
    },
    set(val) { // 设置属性时调用
        objName = val    
    }
})

在vue2中对一个对象中所有的属性进行了遍历,当读取属性是就会调用get方法,设置属性时就会调用set方法

 let obj = {}  // 定义一个对象

    class Vue { // 定义一个类
        $options; // 在类里面定义两个属性
        _data;
        constructor(options) { // 使用constructor给在类里定义的属性赋值
            this.$options = options
            this._data = options.data
            this.initDate() // 因为构造函数不需要调用,在实例化时会自己调用
        }
        initDate() {
            let keys = Object.keys(this._data) // 对一个对象进行循环获取键名形成的数组
            // console.log(keys);
            for (let i in keys) { //对这个数组用 for in 进行循环
                let key = keys[i] // 把对应的键名赋值给key
                Object.defineProperty(this, key, { // 用 Object.defineProperty 进行数据劫持 this代表vm key代表属性名
                    get() {
                        // return this[key]._data
                        return this._data[key] // 把劫持到的属性值在进行读取时返回出去
                    },
                    set(val) {
                        this[key] = val // 在进行设置时劫持数据赋值到vm里
                    }
                })
            }
        }
    }

    let vm = new Vue({
        data: { name: "张三", age: 21 }
    })
    console.log(vm.name);