Jinuss's blog Jinuss's blog
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript高级程序设计》
    • 《Vue》
    • 《React》
    • 《Git》
    • JS设计模式总结
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

东流

前端可视化
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript高级程序设计》
    • 《Vue》
    • 《React》
    • 《Git》
    • JS设计模式总结
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 概览

  • 响应式系统

    • Proxy对象代理
    • effect函数
      • ref和reactive
      • computed函数
      • 响应系统里的工具函数
    • runtime运行时

    • runtime-core

    • compiler编译

    • 《Vue3源码》笔记
    • 响应式系统
    东流
    2024-05-29
    目录

    effect函数

    # 概述

    effect函数是 vue3 响应式系统中的核心函数,是用来创建响应式副作用的重要工具,其内部维护一个dirty属性,该属性用来标识当前副作用是否需要重新执行。

    # effect定义

    effect定义如下:其首先检测参数fn的effect是否是ReactiveEffect的实例,如果是则将effect.fn赋值给参数fn。然后创建一个ReactiveEffect实例(第三个参数scheduler内部是运行_effect.run()),并赋值给_effect;如果定义使用effect时,传入了参数option,则将其传给_effect。如果options或者options.lazy为false,则运行一次_effect.run()。最后,定义一个runner函数,它本质上就是_effect.run,通过bind函数绑定this指向,将_effect赋值给runner的effect属性,最终返回runner。

    function effect(fn, options) {
      if (fn.effect instanceof ReactiveEffect) {
        fn = fn.effect.fn;
      }
      const _effect = new ReactiveEffect(fn, shared.NOOP, () => {
        if (_effect.dirty) {
          _effect.run();
        }
      });
      if (options) {
        shared.extend(_effect, options);
        if (options.scope) recordEffectScope(_effect, options.scope);
      }
      if (!options || !options.lazy) {
        _effect.run();
      }
      const runner = _effect.run.bind(_effect);
      runner.effect = _effect;
      return runner;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20

    effect 从源码上来观察,它更像是调用ReactiveEffect生成的实例的run方法,

    # ReactiveEffect类的实现

    ReactiveEffect类的伪代码如下

    class ReactiveEffect {
      constructor(fn,trigger, scheduler, scheduler) {
        this.fn = fn; // 参数fn
        this.trigger = trigger; // 触发器
        this.scheduler = scheduler; //调度器
        this.active = true; // 是否激活
        this.deps = [];// 依赖函数的集合
        this._dirtyLevel = 4;// 0:不需要任何操作,当前effect是干净的 1:正在检查或查询 2:表示计算属性或副作用可能影响其值 3:类似于2 4:需要更新或者处理
        this._trackId = 0;//递增
        this._runnings = 0;// 运行次数
        this._shouldSchedule = false;// 是否需要调度
        this._depsLength = 0;// 依赖长度
        recordEffectScope(this, scope);
      }
    
      get dirty(){} // 获取脏值 dirtyLevel 的取值
      set dirty(){} //设置脏值 dirtyLevel 的状态 true则设为4,fals 设为0
      run(){}
      stop(){}
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20

    # trackEffect 依赖收集

    trackEffect的作用就是进行依赖收集,其实现如下:

    function trackEffect(effect2, dep, debuggerEventExtraInfo) {
      if (dep.get(effect2) !== effect2._trackId) {
        dep.set(effect2, effect2._trackId);
        const oldDep = effect2.deps[effect2._depsLength];
        if (oldDep !== dep) {
          if (oldDep) {
            cleanupDepEffect(oldDep, effect2);
          }
          effect2.deps[effect2._depsLength++] = dep;
        } else {
          effect2._depsLength++;
        }
        if (true) {
          effect2.onTrack?.(extend({ effect: effect2 }, debuggerEventExtraInfo));
        }
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

    # triggerEffects

    编辑 (opens new window)
    上次更新: 2024/07/23, 11:04:04
    Proxy对象代理
    ref和reactive

    ← Proxy对象代理 ref和reactive→

    最近更新
    01
    GeoJSON
    05-08
    02
    Circle
    04-15
    03
    CircleMarker
    04-15
    更多文章>
    Theme by Vdoing | Copyright © 2024-2025 东流 | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式