Vue3响应式个人理解(五)调度执行

文章参考了霍春阳的《Vue.js设计与实现》,是自己在阅读过程中的一些思考和理解

调度执行

目的是为了让副作用函数拥有可调度性,包括决定副作用函数的执行时机、次数以及方式。

可以给effectfn上添加一个options属性,允许用户指定调度器。即给effect函数添加第二个options参数,将其挂载到effectfn上。代码如下:

  function effect(fn, options = {}) {
    const effectfn = () => {
      clearup(effectfn)
      activeEffect = effectfn
      // 栈设计
      effectStack.push(effectfn)
      fn()
      effectStack.pop()
      activeEffect = effectStack[effectStack.length-1]
    }
    // 新增调度选项挂载
    effectfn.options = options
    effectfn.deps = []
    effectfn()
  }

时机控制

在tirgger函数的执行过程中如果副作用函数存在调度器,则将副作用函数作为参数传递给调度器,进而让用户自己能够决定怎么来执行trigger。代码如下:

 effectsToRun.forEach(effect => {
        // 如果存在调度器,则交给调度器执行,否则按默认行为执行
        if (effect.options.scheduler) {
          effect.options.scheduler(effect)
        } else {
          effect()
        }

次数控制

在调度器的基础上新增任务队列,代码如下:

// 任务队列
const queue = new Set()
// 使用Promise.resolve()创建一个Promise实例,用它将任务添加到微任务队列
const p = Promise.resolve()

// 标志代表是否正在刷新对了
let isFlushing = false

function flushJob() {
  // 如果正在刷新,则直接返回
  if(isFlushing) return
  // 加锁
  isFlushing = true
  // 在微任务队列中刷新queue队列
  p.then(() => {
    flushJob.forEach(job => job())
  }).finally(() => {
    // 结束后重置
    isFlushing = false
  })
}

effect(() => {
  console.log(obj.num)
}, {
  scheduler(fn) {
    queue.add(fn)
    flushJob()
  }
})

目前的问题:假设要连续增加一个数的值,但是我们只想看到最初和最后的值。

首先定义了一个queue队列,用的Set集合,利用其特性可以实现自动去重。在trigger执行时,发现副作用函数有调度器,将函数扔给调度器执行,调度器中添加该函数,然后执行flushJob函数。通过isFlushing判断当前函数是否已经在执行了,这个标志是为了让函数中一个周期内,只执行一次而不是对每个副作用函数都执行。而副作用函的执行是在promise的微队列中进行。

因此整体的看,对于自增的操作,每次的自增都会调用trigger,但是有调度器的Set集合存在,相同的effectfn函数不会添加到队列中;而flushJob函数由于有isFlushing标志位的存在,页不会每次都执行;最后由于Promise微队列的存在,使得在最后才会执行effectfn,且只会执行一次,而当它执行时,自增操作已经结束了,进而我们只会看到最初和最后的值。最初的值是在effect函数中执行看到的。

这个功能类似在Vue中的连续修改响应式的值,但数据只会触发一次更新。思路是相同的,这里需要看源码。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值