Vue3开发(五)之响应式原理

97 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第5天,点击查看活动详情

前言

上一章我们在分析代码时学习了Vue3的响应式数据,这一章我们一起来了解下响应式原理。

一、Vue2中的响应式

  • 实现原理:
    • 对象类型:通过Object.defineProperty()对属性的读取、修改进行拦截(数据劫持)。
    • 数组类型:通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)
     Object.defineProgerty(data, 'count', {
        get(){},
        set(){}
      })
    
  • 存在问题:
    • 新增属性、删除属性,界面不会更新
    • 直接通过下标修改数组,界面不会自动更新
  • 解决方案
    • 使用this.$set(this.person,'sex','女')或者Vue.set(this.person,'sex','女')添加属性,界面就能刷新了
    • 使用this.$delete(this.person,'sex','女')或者Vue.delete(this.person,'sex','女')删除属性,界面就能刷新了
    • 对于数组,也可以用this.和Vue.方法修改,如:this.$set(this.person.hobby,0,'学习'),第二个参数是数组下标
    • 对于数组,数组上有个splice方法,用这个也可以解决,如:this.person.hobby.splice(0,1,'学习')

二、Vue3中的响应式

  • 实现原理
    • 通过Proxy(代理):拦截对象中任意属性的变化,包括:属性值的读写、属性的添加、属性的删除等。(在Vue3中主要感谢reactive,避免了Vue2上面提到的问题)
    const person = {
        name:'张三',
        age:18
    }
    const p = new Proxy(person,{
        get(target,propName){
          console.log('读取了属性');
          return target[propName]; // 在操作源数据
        },
        set(target,propName,value){
          console.log('修改或追加属性,将通知界面更新');
          target[propName] = value; // 在操作源数据
        },
        deleteProperty(target,propName){
          console.log('删除了属性,将通知界面更新');
          return delete target[propName]; // 在操作源数据
        }
    })
    
    • 通过Reflect(反射): 对源对象的属性进行操作。
    const person = {
        name:"张三",
        age:18
    }
    const p = new Proxy(person,{
        get(target,propName){
          console.log("读取了属性");
          return Reflect.get(target,propName);
        },
        set(target,propName,value){
          console.log("修改了属性,将通知界面更新");
          return Reflect.set(target,propName,value);
        },
        deleteProperty(target,propName){
          console.log("删除了属性,将通知界面更新");
          return Reflect.deleteProperty(target,propName);
        }
    })
    

结束语

这一章我们学习了响应式,了解了响应式原理,下一章我们一起学习计算属性与监视。