1.vue2.x的响应式

  • 实现原理:

    • 对象类型:通过Object.defineProperty()对属性的读取、修改进行拦截(数据劫持)。

    • 数组类型:通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)。

      Object.defineProperty(data, 'count', {
          get () {}, 
          set () {}
      })
  • 存在问题:

    • 新增属性、删除属性, 界面不会更新。
    • 直接通过下标修改数组, 界面不会自动更新。

2.Vue3.0的响应式

new Proxy(data, {
    // 拦截读取属性值
    get (target, prop) {
        return Reflect.get(target, prop)
    },
    // 拦截设置属性值或添加新属性
    set (target, prop, value) {
        return Reflect.set(target, prop, value)
    },
    // 拦截删除属性
    deleteProperty (target, prop) {
        return Reflect.deleteProperty(target, prop)
    }
})

proxy.name = 'tom'   
  var person = {
            name: "张三",
            age: 12
        }
        var proxy = new Proxy(person, {
            get(target, attr) {
                console.log("获取属性时触发!")
                // return "哈哈哈"
                // return target[attr];
                return Reflect.get(target, attr);

            },
            set(target, attr, value) {
                console.log("触发了set");
                //target[attr] = value;
                return Reflect.set(target, attr, value);

            },
            deleteProperty(target, attr) {
                console.log("删除了属性")
                //delete target[attr];
                return Reflect.deleteProperty(target, attr)
            }
        })

        console.log(proxy.name);
        proxy.name = "李四"
        delete proxy.age
        console.log(proxy);

        var obj = {
            name: "李四"
        }
         //重复性添加属性会报错
        // try {
        //     Object.defineProperty(obj, "title", {
        //         get() {
        //             return "欢迎访问!!"
        //         }
        //     })

        //     Object.defineProperty(obj, "title", {
        //         get() {
        //             return "欢迎访问!!"
        //         }
        //     })
        // } catch (error) {
        //     console.log(error)
        // }

        const result1 = Reflect.defineProperty(obj, "title", {
            get() {
                return "欢迎访问!!"
            }
        })
        const result2 = Reflect.defineProperty(obj, "title", {
            get() {
                return "欢迎访问!!"
            }
        })
        console.log(result1, result2) //true  false
        if (result2) {
            console.log("下面要执行的语句!!")
        } else {
            console.log("代码错误!!")
        }

reflect存在的意义:

1,将object对象一些内部的方法,放到Reflect对象上。比如:object.defineProperty

说明:现阶段这些方法存在于object和Reflect对象上,未来只存在于Reflect对象上。

意义:也就是说,从Reflect对象上可以拿到语言内部的方法。

2,操作对象时出现报错返回false

说明:比如,Object.defineProperty(obj, name, desc)在无法定义属性时,会抛出一个错误,而Reflect.defineProperty(obj, name, desc)则会返回false。

// 老写法
try {
  Object.defineProperty(target, property, attributes);
  // success
} catch (e) {
  // failure
}

// 新写法
if (Reflect.defineProperty(target, property, attributes)) {
  // success
} else {
  // failure
}

3,让操作对象的编程变为函数式编程

说明:老写法有的是命令式编程,比如下面这个例子

// 老写法
'assign' in Object // true

// 新写法
Reflect.has(Object, 'assign') // true

4,保持和proxy对象的方法一一对应

说明:Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。

Proxy(target, {
  set: function(target, name, value, receiver) {
    var success = Reflect.set(target, name, value, receiver);
    if (success) {
      console.log('property ' + name + ' on ' + target + ' set to ' + value);
    }
    return success;
  }
});

总结:综上所述,Reflect对象有4个意义:

(1)从Reflect对象上可以拿到语言内部的方法。
(2)操作对象出现报错时返回false
(3)让操作对象都变为函数式编程
(4)保持和proxy对象的方法一一对象

文档更新时间: 2023-08-11 15:14   作者:董老师