Vue2和Vue3响应式数据的区别

110 阅读2分钟

Vue2

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

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

底层实现:

通过对象属性拦截的方式实现,但是无法监听删除和添加

 const person = {
     name: 'ls',
     age: 17
 }
 // 静态代理的方式实现 用p 来代理 person
 const p = {}
 Object.defineProperty(p, 'name', { // Object.keys(person) 循环每一个属性执行 Object.dfineProperty() 实现每个属性的代理
     configurble: true, // 允许删除
     // 有人读取 name 时触发
     get() {
         return person.name // 将读取的结果返回
     },
     // 有人修改 name 时触发
     set(value) { // 修改后的值
         person.name = value // 将值修改
     }
 })

缺点:

对象类型: 新增属性、删除属性,界面不更新

数组类型: 直接通过下标修改数组,界面不会更新

解决方法:

数组可以使用vue.set()方法和数组的splice方法

置空数组重新赋值也行

 // 对象类型
 vue.$set(要修改的对象, 添加的属性名,属性值)
 this.$set() // 同上
 this.$delete(要修改的对象,要删除的属性名) 
 ​
 // 数组类型
 this.$set(要修改的数组, 下标, 值)
 this.$delete(要修改的数组,下标) 
 Array.splice(0,1, '逛街') // 也能解决 或者置空数组重新赋值

Vue3

通过Proxy对象整体代理,拦截对象中任意属性的变化,包括属性的读写,属性的添加,属性的删除等等

通过Reflect反射对象:对原文件进行操作

 const person = {
     name: 'ls',
     age: 17
 }
 const p = new Proxy(person, {
     // 读取p某个属性时调用 target为原对象 propName为读取的属性
     get(target, propName) {
           // 参数一 要查找的对象 不是对象会报错   
          // 参数二 要查找的属性
         // 参数三 如果读取的对象属性部署了读取函数getter,则读取函数的this绑定参数三
         return Reflect.get(target, propName) // 返回读取的结果,没有属性则返回undefined 不会报错,更有利于框架的开发
     },
     // 有人修改person的某个属性,或给person追加某个属性时调用
     set(target, propName, value) { // target为原对象 propName为修改或增加的属性,value修改或增加的值
            // 参数一 要修改的对象
           // 参数二 要修改的属性
          // 参数三 修改的值
         // 参数四 同上述Reflect.get方法参数三描述
         return Reflect.set(target, propName, value) // 返回布尔值表示是否删除属性成功
     },
     // 有人删除 person 的某个属性时调用
     deleteProperty(target, propName) {  // target为原对象 propName为删除的属性
         // 等同于 delete obj[name] 用于删除对象中的属性
         return Reflect.deleteProperty(target, propName) // 返回一个布尔值,成功为true,反之为false
     }
 })