vue3中effect函数中收集依赖,触发依赖代码实现

  想要理解vue3的响应式是如何实现的,就需要学习effect函数的相关内容,百闻不如一练,这篇文章咱们一块学习effect函数手撕代码的实现。

开端

  声明一个响应式对象,通过effect函数对响应式对象进行包裹,这部分代码如下图:

   先看声明响应式reactive里面的内容,它返回一个代理对象,并通过Reflect实现了get和set方法,如下图:

  然后再看effect函数的具体内容,在effect中利用面向对象思想,定义一个ReactiveEffect类,类中定义接收依赖的变量,并在构造方法中获取到相应的依赖,声明run函数用来执行依赖,最后抛出接收了依赖参数的effect函数,并调用run函数执行依赖,如下图:

  下面来看收集依赖的track函数和触发依赖的trigger函数的实现。

收集依赖

  track函数用map来建立target和depsMap之间的映射关系,在收集依赖的时候获取到当前对象,并进行对象是否为空的判断,如果为空就进行一次赋值,用set来建立key和dep之间的映射关系,也进行判空操作,之后在dep中储存响应式依赖,如下图:

触发依赖

  在trigger函数中,根据target和key获取相应的dep,通过for of遍历dep中的依赖,调用run函数触发依赖,如下图:

完整代码

effect.spec.ts

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

describe("effect", () => {
    it.skip("happy path", () => {
        const user = reactive({
            age: 20,
        });

        let nextAge;

        effect(() => {
            nextAge = user.age + 1;
        });
    })
})

effect.ts

class  ReactiveEffect {
    private _fn: any;

    constructor(fn) {
        this._fn = fn;
    }
    run() {
        activeEffect = this;
        this._fn();
    }
}

const targetMap = new Map()
export function track(target, key) {
    let depsMap = targetMap.get(target);
    if (!depsMap) {
        depsMap = new Map();
        targetMap.set(target, depsMap);
    }

    let dep = depsMap.get(key);
    if (!dep) {
        dep = new Set();
        depsMap.set(key, dep);
    }
    dep.add(activeEffect);
}

export function trigger(target, key) {
        let depsMap = targetMap.get(target)
        let dep = depsMap.get(key)

        for(const effect of dep) {
            effect.run();
        }
}

let activeEffect;
export function effect(fn) {
    const _effect = new ReactiveEffect(fn);

    _effect.run();
}

reactive.spec.ts

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

describe('reactive', () => {
    it('happy path', () => {
        const original = { foo:1 };
        const observed = reactive(original);
    });
});

reactive.ts

import { track, trigger } from './effect'

export function reactive (raw) {
    return new Proxy(raw, {
 
        get(target,key){
            const res = Reflect.get(target,key);
            track(target, key);
            return res;
        },
        
        set(target, key, value) {
            const res = Reflect.set(target, key, value);
            trigger(target, key)
            return res;
        }
    })
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值