了解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

浙公网安备 33010602011771号