Vue 3.0 reactive/effect

reactive.js:

import { isObject } from "../utils";
import { track, trigger } from "./effect";

export function reactive(target) {
    // 判断 target 类型
    // 如果是基本类型,则不将其转化成响应式
    if (!isObject(target)) return target;

    const proxy = new Proxy(target, {
        get(target, key, receiver) {
            const res = Reflect.get(target, key, receiver);
            
            // 收集依赖
            track(target, key);
            
            return res;
        },
        set(target, key, value, receiver) {
            const res = Reflect.get(target, key, value, receiver);
            
            // 触发依赖
            trigger(target, key);
            
            return res;
        }
    });

    return proxy;
}

 

effect.js:

// 记录当前正在执行的副作用函数
let activeEffect;

/** 难点
 * 一个副作用函数可能依赖多个响应式数据
 * 一个响应式数据更新可能会触发多个副作用函数
 * 因此 targetMap 的结构是:
 * {
 *      [target]: {
 *          [key]: []
 *      }
 * }
 * 使用 WeakMap 是因为不需要手动删除不需要的依赖
 */ 
const targetMap = new WeakMap();

export function effect(fn) {
    const effectFn = () => {
        try {
            activeEffect = effectFn;
            return fn();
        } finally {
            // todo
        }
    }

    effectFn();
    return effectFn;
}

export function track(target, key) {
    if (!activeEffect) return;

    let depsMap = targetMap.get(target);
    
    // 初始化时一定是不存在的
    if (!depsMap) targetMap.set(target, (depsMap = new Map()));

    let deps = depsMap.get(key);
    // 同样,初始化的时候一定无值
    if (!deps) depsMap.set(key, (deps = new Set()));

    deps.add(activeEffect);

    console.log(targetMap, key)
}

export function trigger(target, key) {
    const depsMap = targetMap.get(target);

    if (!depsMap) return;

    const deps = depsMap.get(key)
    
    if (!deps) return;

    deps.forEach(effectFn => {
        effectFn();
    });
}

 

index.js(入口文件):

import { reactive } from "./reactive/reactive";
import { effect } from "./reactive/effect";

const observed = reactive({
    count: 0
});

effect(() => {
    console.log(observed.count)
})

 

posted @ 2023-07-05 18:37  shiweiqianju  阅读(26)  评论(0编辑  收藏  举报