KING 博主等级

一帆风顺 ⛵️⛵️⛵️

Vue3响应式原理

钟晓川
2023-06-26 / 2 点赞 / 771 阅读

vue2.x的响应式

  • 实现原理

    • 对象类型:通过Object.defineProperty()对属性的读取、修改进行拦截(数据劫持)
    • 数组类型:通过重写更新数组的一系列方法来实现拦截(对数组的变更方法进行了包裹)
  • 存在的问题

    • 新增属性、删除属性 界面不会更新
    • 直接通过下标修改数组 界面不会自动更新
    // 源数据
    let person = {
        name: '张三',
        age: 22
    }
    let p = {}
    Object.defineProperty(p, 'name', {
        configurable: true,
        // 读取name时调用
        get() {
            console.log('有人读取了name属性,我发现了,我要去更新界面!')
            return person.name
        },
        // 修改name时调用
        set(value) {
            console.log('有人修改了name属性,我发现了,我要去更新界面!')
            person.name = value
        }
    })
    
    Object.defineProperty(p, 'age', {
        configurable: true,
        // 读取name时调用
        get() {
            console.log('有人读取了name属性,我发现了,我要去更新界面!')
            return person.age
        },
        // 修改name时调用
        set(value) {
            console.log('有人修改了name属性,我发现了,我要去更新界面!')
            person.name = age
        }
    })

vue3.x的响应式

  • 实现原理
    • 通过Proxy(代理):拦截对象中任意属性的变化,包括:属性值的读写、添加删除等

    • 通过Reflect(反射):对源对象的属性进行操作

    • MDN文档中描述的Proxy与Reflect:

      • Proxy:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy
      • Reflect:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect
      // 源数据
      let person = {
          name: '张三',
          age: 22
      }
      const p = new Proxy(person, {
          // 有人读取p的某个属性时调用
          get(target, propName) {
              console.log(`有人读取了p身上的${propName}属性`)
              return Reflect.get(target, propName)
          },
          // 有人修改p的某个属性 或给p追加某个属性时调用
          set(target, propName, value) {
              console.log(`有人修改了p身上的${propName}属性,我要去更新界面了!`)
              Reflect.set(target, propName, value);
          },
          // 有人删除p的某个属性时调用
          deleteProperty(target, propName) {
              console.log(`有人删除了p身上的${propName}属性,我要去更新界面了!`)
              return Reflect.deleteProperty(target, propName)
          }
      })
2