【Vue.js 3.0源码】响应式之内部实现原理(下)

自我介绍:大家好,我是吉帅振的网络日志;微信公众号:吉帅振的网络日志;前端开发工程师,工作4年,去过上海、北京,经历创业公司,进过大厂,现在郑州敲代码。

一、前言

【Vue.js 3.0源码】响应式之内部实现原理(上) 中说到 Vue.js 3.0 中引入 reactive API,它可以把对象数据变成响应式,收集依赖的 get 函数,接下来我们来分析 reactive API 中需要关注的另一个内容——派发通知的过程。

二、派发通知:set 函数

派发通知发生在数据更新的阶段 ,由于我们用 Proxy API 劫持了数据对象,所以当这个响应式对象属性更新的时候就会执行 set 函数。我们来看一下 set 函数的实现,它是执行 createSetter 函数的返回值:

function createSetter() {
  return function set(target, key, value, receiver) {
    const oldValue = target[key]
    value = toRaw(value)
    const hadKey = hasOwn(target, key)
    const result = Reflect.set(target, key, value, receiver)
    // 如果目标的原型链也是一个 proxy,通过 Reflect.set 修改原型链上的属性会再次触发 setter,这种情况下就没必要触发两次 trigger 了
    if (target === toRaw(receiver)) {
      if (!hadKey) {
        trigger(target, "add" /* ADD */, key, value)
      }
      else if (hasChanged(value, oldValue)) {
        trigger(target, "set" /* SET */, key, value, oldValue)
      }
    }
    return result
  }
}

结合上述代码来看,set 函数的实现逻辑很简单,主要就做两件事情, 首先通过 Reflect.set 求值 , 然后通过 trigger 函数派发通知 ,并依据 key 是否存在于 target 上来确定通知类型,即新增还是修改。整个 set 函数最核心的部分就是 执行 trigger 函数派发通知 ,下面我们将重点分析这个过程。我们先来看一下 trigger 函数的实现,为了分析主要流程,这里省略了 trigger 函数中的一些分支逻辑:

// 原始数据对象 map
const targetMap = new WeakMap()
function trigger(target, type, key, newValue) {
  // 通过 targetMap 拿到 target 对应的依赖集合
  const depsMap = targetMap.get(target)
  if (!depsMap) {
    // 没有依赖,直接返回
    return
  }
  // 创建运行的 effects 集合
  const effects = new Set()
  // 添加 effects 的函数
  const add = (effectsToAdd) => {
    if (effectsToAdd) {
      effectsToAdd.forEach(effect => {
        effects.add(effect)
      })
    }
  }
  // SET | ADD | DELETE 操作之一,添加对应的 effects
  if (key !== void 0) {
    add(depsMap.get(key))
  }
  const run = (effect) => {
    // 调度执行
    if (effect.options.scheduler) {
      effect.options.scheduler(effect)
    }
    else {
      // 直接运行
      effect()
    }
  }
  // 遍历执行 effects
  effects.forEach(run)
}

trigger 函数的实现也很简单,主要做了四件事情:通过 targetMap 拿到 target 对应的依赖集合 depsMap;创建运行的 effects 集合;根据 key 从 depsMap 中找到对应的 effects 添加到 effects 集合;遍历 effects 执行相关的副作用函数。

所以每次 trigger 函数就是根据 target 和 key ,从 targetMap 中找到相关的所有副作用函数遍历执行一遍。在描述依赖收集和派发通知的过程中,我们都提到了一个词:副作用函数,依赖收集过程中我们把 activeEffect(当前激活副作用函数)作为依赖收集,它又是什么?接下来我们来看一下副作用函数的庐山真面目。

三、副作用函数

介绍副作用函数前,我们先回顾一下响应式的原始

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值