最近在学习vue3 记录下
先实现最简单的
let obj = { name: 'jw', age: 30, address: '222' }
const state = reactive(obj);
effect(() => {
document.getElementById('app').innerHTML = state.age + state.name
})
reactive的现实
function reactive(target) {
// 对传进来的做一层proxy代理
const proxy = new Proxy(target, mutableHandlers);
return proxy;
}
effect实现
export class ReactiveEffect {
public active = true;
public deps = [];
public parent = undefined;
constructor(public fn,) {
}
run() {
try {
this.parent = activeEffect;
activeEffect = this;
return this.fn(); // 这个地方做了依赖收集
} finally {
activeEffect = this.parent;
this.parent = undefined;
}
}
}
// 依赖收集 就是将当前的effect变成全局的 稍后取值的时候可以拿到这个全局的effect
export function effect(fn) {
const _effect = new ReactiveEffect(fn);
_effect.run(); // 默认让响应式的effect执行一次
}
默认会执行 effect一次 执行的话 会有取值的操作 这个时候就会触发依赖的收集
mutableHandlers
export const mutableHandlers = {
get(target, key, receiver) {
// 标记这个对象是响应式
if (ReactiveFlags.IS_REACTIVE == key) {
return true;
}
// 收集依赖
track(target, key);
let r = Reflect.get(target, key, receiver); // 处理了this问题
if (isObject(r)) {
// 只有用户取值的时候 才会进行二次代理,不用担心性能
return reactive(r);
}
return r;
},
set(target, key, value, receiver) {
// 用户赋值的操作
let oldValue = target[key]; // 没有修改之前的值
// set 方法的返回值是一个boolean
let r = Reflect.set(target, key, value, receiver);
if (oldValue !== value) {
trigger(target, key, value, oldValue);
}
return r;
},
};
get的时候 收集依赖
weakMap {obj: map{key: set(effect)}} 这样一个结构
set的时候 触发执行
从这个weakMap中 去除 对应的 effect去执行一次 触发更新
有兴趣的 查看完整源码 gitee.com/FanBingKun/…
自律