IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 【mini-vue3】实现思路文档——reactivity -> 正文阅读

[JavaScript知识库]【mini-vue3】实现思路文档——reactivity

本文记录实现一个 mini-vue3 的关键点,用来辅助自己从 0 到 1 实现一个 mini-vue3。

dep

createDep(effects?):

  • 作用:创建 dep
  • 主要逻辑:
    • 使用 Set 存储 ReactiveEffect 的实例对象

reactive

缓存

export const reactiveMap = new WeakMap();
export const readonlyMap = new WeakMap();
export const shallowReadonlyMap = new WeakMap();

reactive(target):

  • 作用:转成响应式对象
  • 参数:
    • target:对象
  • 主要逻辑:
    • createReactiveObject(target, reactiveMap, mutableHandlers)

createReactiveObject(target, proxyMap, baseHandlers):

  • 参数:
    • proxyMap:缓存
    • baseHandlers:操作器,查看 baseHandlers.md
  • 主要逻辑:
    • 判断是否有缓存,有缓存直接返回
    • 使用 proxy
    • 将返回的 proxy 对象加入缓存

readonly(target):

  • createReactiveObject(target, readonlyMap, readonlyHandlers);

shallowReadonly(target):

  • createReactiveObject(target, shallowReadonlyMap, shallowReadonlyHandlers);

isProxy(value):

  • isReactive(value) || isReadonly(value);

isReactive(value):

  • 主要逻辑:
    • !!value[ReactiveFlags.IS_REACTIVE];
    • 若 value 是 proxy,则会调用 get,转 baseHandlers 的 createGetter 函数返回布尔值
    • 否则为 undefined,!! 转布尔值

isReadonly(value):

  • !!value[ReactiveFlags.IS_READONLY];

toRaw(value):

  • 主要逻辑:
    • 若 value 是 proxy,转 baseHandlers 的 createGetter 函数直接返回
    • 否则为 undefined 直接返回原 value

baseHandlers

createGetter(isReadonly: boolean, shallow: boolean)

  • 作用:用于 proxy 中的 get 操作器
  • 参数:
    • isReadonly 是否是 readonly
    • shallow 是否是 shallow
  • 主要逻辑:
    • 返回与 proxy 格式相同的 get 函数(即 get 操作器)
    • 根据 key、receiver 判断,被用于 isReactive、isReadonly、isRaw 函数
      • 若 key === ReactiveFlags.IS_REACTIVE,返回 !isReadonly
      • 若 key === key === ReactiveFlags.IS_READONLY,返回 isReadonly
      • 若 key === ReactiveFlags.RAW 并且存在某个缓存中,即存在响应式对象,直接返回 target
    • 使用 Reflect.get 获取值
    • 调用 track 函数进行依赖收集,注意 readonly 不需要
    • shallow 直接返回结果
    • 若返回值为对象,reactive 需要对其调用 reactive 再返回

createSetter()

  • 作用:用于 proxy 中的 set 操作器
  • 主要逻辑:
    • 返回 set 函数
    • 触发依赖

mutableHandlers()

  • 作用:封装 reactive 的操作器,使用 createGetter()、createSetter()

readonlyHandlers()

  • 作用:封装 readonly 的操作器,仅使用 createGetter(true)

shallowReadonlyHandlers()

  • 作用:封装 shallowReadonly 的操作器,仅使用 createGetter(true, true)

effect

变量注解

  • dep:为 Set,保存 ReactiveEffect 的实例
  • effect:ReactiveEffect 的实例

effect(fn, options = {}):

  • 作用:入口函数
  • 参数:
    • fn:依赖的函数
    • options:配置,可传入 scheduler 或 onStop
  • 主要逻辑:
    • 创建 ReactiveEffect 实例
    • 将 option 合并到实例中
    • 使用实例执行 run 方法
    • 实例的 run 方法绑定 this 为该实例并赋值给变量 runner(让用户可自行选择调用时机)
    • 在 runner 对象上挂载 effect 方法指向该实例(是为了 triggerEffects 函数可以调用实例上的方法(比如 scheduler))
    • 返回 runner

全局变量

  • let activeEffect = void 0:用于获取执行函数的 ReactiveEffect 封装
  • let shouldTrack = false
  • const targetMap = new WeakMap()

class ReactiveEffect:

  • 作用:其实例为依赖项的封装
  • 值:
    • active = true:是否需要收集依赖
    • deps = []:依赖项对响应式对象的依赖
    • onStop?: () => void:清除依赖的回调函数

constructor(public fn, public scheduler?):

  • 参数:
    • scheduler:回调函数。当触发依赖时,不调用 fn 而是调用 scheduler,逻辑在 isTracking 函数。computed 的实现逻辑就使用了该参数

run():

  • 作用:进行依赖收集
  • 主要逻辑:
    • 判断 active
    • 开启依赖收集:shouldTrack = true、activeEffect = this
    • 重置,关闭收集依赖

stop():

  • 作用:清除依赖项对响应式对象的依赖
  • 主要逻辑:
    • 若 active 为 true,执行 cleanupEffect、onStop
    • active = false

cleanupEffect(effect):

  • 作用:清除操作
  • 主要逻辑:
    • 删除 deps 中所有 set 的 effect
    • deps.length = 0

track(target, type, key):

  • 作用:查找 target 对应的 depsMap 对应的属性依赖项 dep,用于 get
  • 主要逻辑:
    • isTracking 函数判断
    • 有相关的数据结构直接获取,没有则创建
      • depsMap = targetMap.get(target)
      • dep = depsMap.get(key)
    • trackEffects(dep)

trackEffects(dep):

  • 作用:收集依赖
  • 主要逻辑:
    • dep.add(activeEffect)
    • activeEffect.deps.push(dep)

trigger(target, type, key):

  • 作用:触发依赖,用于 set
  • 主要逻辑:
    • 获取 dep,同上
    • 将 deps 的所有 dep 合并为一个 dep,传入 triggerEffects 函数

isTracking():

  • shouldTrack && activeEffect !== undefined

triggerEffects(dep):

  • 主要逻辑:
    • 遍历 dep,若 effect 有 scheduler 方法则执行,否则执行 run 方法

ref

ref(value):

  • 作用:入口函数
  • createRef(value)

class RefImp:

  • 变量:
    • __rawValue:保存原始对象
    • _value:保存 ref 对象
    • dep
    • __v_isRef:是否 ref

constructor(value):

  • 作用:创建一个 ref 对象
  • 主要逻辑:
    • __value = convert(value)
    • dep = createDep()

get value():

  • trackRefValue(this)

set value(newValue):

  • 主要逻辑:
    • hasChanged 对新旧值判断
    • triggerRefValue(this)

convert(value):

  • isObject(value) ? reactive(value) : value

createRef(value):

  • new RefImpl(value)

triggerRefValue(ref):

  • triggerEffects(ref.dep)

trackRefValue(ref):

  • trackEffects(ref.dep)

对象:shallowUnwrapHandlers

  • get(target, key, receiver):unRef(Reflect.get(target, key, receiver))
  • set(target, key, value, receiver):Reflect.set(target, key, value, receiver)

proxyRefs(objectWithRefs):

  • 作用:浅解包
  • 主要逻辑:
    • new Proxy(objectWithRefs, shallowUnwrapHandlers)

unRef(ref):

  • isRef(ref) ? ref.value : ref

isRef(value):

  • !!value.__v_isRef

computed

computed(getter):

  • 作用:入口函数
  • new ComputedRefImpl(getter)

class ComputedRefImpl:

  • 变量:
    • dep
    • effect
    • _dirty:锁
    • _value

constructor(getter):

  • 主要逻辑:
    • new ReactiveEffect(getter, scheduler)
    • scheduler 中进行解锁,并执行 triggerRefValue 触发依赖

get value()

  • 主要逻辑:
    • 依赖收集
    • 若上锁状态,则不执行 effect.run(),以此达到缓存的效果
    • 即 computed 的依赖触发是在 get 而不是在 set

结尾

本文所提到的实现思路来自于大佬 cuixiaorui 的 mini-vue
同时附上本人的 mini-vue 仓库

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-06 16:08:57  更:2022-04-06 16:13:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:11:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码