基于Vue3从0到1实现 mini-vue【computed】

基于Vue3从0到1实现 mini-vue【computed】

✨代码已上传至CSDN文库,如需要请点击下载min-vue,私信也可免费提供代码。
✨运行顺序 npm install ==>npm run build ==>npm run dev
✨Github mini-vue

目录结构详 基于Vue3从0到1实现 mini-vue【reactive】

conputed 只有在相关响应式依赖的值发生改变时才会重新计算,并具有缓存属性。

添加src/untils/index.js方法


export function isFunction(target){
  return typeof target === 'function'
}

新建src/reactive/computed.js


import { isFunction } from '../untils';
import { effect, track, trigger } from './effect';

//参数getterOrOption getter或者get&set对象
export function computed(getterOrOption) {
  let getter, setter;
  if (isFunction(getterOrOption)) {
    getter = getterOrOption;
    setter = () => {
      console.error('computed is readonly');
    };
  } else {
    getter = getterOrOption.get;
    setter = getterOrOption.set;
  }
  return new ComputedImpl(getter, setter);
}

class ComputedImpl {
  constructor(getter, setter) {
    this._setter = setter;
    //value缓存值
    this._value = undefined;
    //依赖更新变为true
    this._dirty = true;
    //默认不立即执行,直接执行scheduler
    this.effect = effect(getter, {
      lazy: true,
      scheduler: () => {
        //调度程序
        if (!this._dirty) {
          this._dirty = true;
          trigger(this, 'value');
        }
      },
    });
  }
  get value() {
    if (this._dirty) {
      this._value = this.effect(); //最新值
      //依赖发生改变
      this._dirty = false;
      track(this, 'value');
    }
    return this._value;
  }
  set value(newValue) {
    this._setter(newValue);
  }
}

更新src/reactive/effect.js

新增 effect 函数入参 options 如果 lazy 为 true 初始化时不立即执行,去执行调度函数 scheduler ,触发 trigger 返回当前值。当依赖的响应式数据变化时执行。

const effectStack = []; //处理effect嵌套effect
let activeEffect; //记录当前正在执行的副作用函数
export function effect(fn, options = {}) {
  const effectFn = () => {
    try {
      activeEffect = effectFn;
      effectStack.push(activeEffect);
      return fn();
    } finally {
      //执行完成后还原
      effectStack.pop();
      //activeEffect = undefined;
      activeEffect = effectStack[effectStack.length - 1];
    }
  };
  if (!options.lazy) {
    effectFn();
  }
  effectFn.scheduler = options.scheduler;
  return effectFn;
}

const targetMap = new WeakMap(); //模块类全局变量

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);
}

//trck的逆运算
export function trigger(target, key) {
  const depsMap = targetMap.get(target);
  if (!depsMap) {
    return;
  }
  const deps = depsMap.get(key);

  if (!deps) {
    return;
  }
  deps.forEach((effectFn) => {
    if (effectFn.scheduler) {
      //有调度程序优先执行scheduler
      effectFn.scheduler(effectFn);
    } else {
     //否则执行副作用函数
      effectFn();
    }
  });
}

comouted计算属性效果

在这里插入图片描述

在这里插入图片描述

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@才华有限公司

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值