了解Vue2Vue3响应式原理源码

我们都知道Vue3使用Proxy代理,因为Vue2在处理数组时,Object.defineProperty的this指向有问题,因为target[key]这种获取值的方式,会导致proxy触发target时候指向的对象就是target而不是Proxy本身,Vue2所以重写了数组的7个方法

const target = {
  value: 42,
  get valuePlusOne() {
    return this.value + 1; // 这里的 this 指向 target
  }
};

const handler = {
  get(target, key) {
    return target[key]; // 直接使用 target[key]
  }
};

const proxy = new Proxy(target, handler);

console.log(proxy.valuePlusOne); // 输出: undefined

<details>
<summary>点击查看代码</summary>

所以Vue3使用Reflect.get来获取,receiver可以保证this的传递,让他指向Proxy
reactive.ts

import {track,trigger} from './effect'
 
 
export const reactive = <T extends object>(target:T) => {
    return new Proxy(target,{
        get (target,key,receiver) {
          const res  = Reflect.get(target,key,receiver) as object
 
          track(target,key)
 
          return res
        },
        set (target,key,value,receiver) {
           const res = Reflect.set(target,key,value,receiver)
 
           trigger(target,key)
 
           return res
        }
    })
}

effect.ts

export const effect = (fn: Function) => {
  const _effect = () => {
    activeEffect = _effect
    fn()
  }
  _effect()
}

const targetMap = new WeakMap()
export const track = (target,key) =>{
   let depsMap = targetMap.get(target)
   if(!depsMap){
       depsMap = new Map()
       targetMap.set(target,depsMap)
   }
   let deps = depsMap.get(key)
   if(!deps){
      deps = new Set()
      depsMap.set(key,deps)
   }
 
   deps.add(activeEffect)
}


export const trigger = (target,key) => {
  const depsMap = targetMap.get(target)
  const deps = depsMap.get(key)
  deps.forEach(effect=>effect())
}

effect函数:就是一个闭包函数,然后定义一个全局变量收集这个函数
track函数:收集依赖
trigger函数:更新依赖

接下来就是Effect收集副作用,然后在get函数中调用收集依赖,在set函数中更新依赖就好了

target函数的数据结构

如果要对深层次Object也进行劫持,需要递归调用reactive即可
代码如下:

import { track, trigger } from './effect'
 
const isObject = (target) => target != null && typeof target == 'object'
 
export const reactive = <T extends object>(target: T) => {
    return new Proxy(target, {
        get(target, key, receiver) {
            const res = Reflect.get(target, key, receiver) as object
 
            track(target, key)
 
            if (isObject(res)) {
                return reactive(res)
            }
 
            return res
        },
        set(target, key, value, receiver) {
            const res = Reflect.set(target, key, value, receiver)
 
            trigger(target, key)
 
            return res
        }
    })
}

然后Object深层的更新也变成响应式啦~

参考文章:https://xiaoman.blog.csdn.net/article/details/127563892

posted @ 2024-08-26 21:34  卡优卡1255  阅读(7)  评论(0)    收藏  举报