Vue.js 设计与实现
霍春阳(HcySunYang)
Vue.js 官方团队成员
340 人已学习
立即订阅
Vue.js 设计与实现
15
15
1.0x
00:00/00:00
登录|注册

第 4 章 响应系统的作用与实现(2)

4.7 调度执行

可调度性是响应系统非常重要的特性。首先我们需要明确什么是可调度性。所谓可调度,指的是当 trigger 动作触发副作用函数重新执行时,有能力决定副作用函数执行的时机、次数以及方式。
首先来看一下,如何决定副作用函数的执行方式,以下面的代码为例:
const data = { foo: 1 }
const obj = new Proxy(data, { /* ... */ })
effect(() => {
console.log(obj.foo)
})
obj.foo++
console.log(‘结束了’)
在副作用函数中,我们首先使用 console.log 语句打印 obj.foo 的值,接着对 obj.foo 执行自增操作,最后使用 console.log 语句打印 '结束了'。这段代码的输出结果如下:
1
2
'结束了'
现在假设需求有变,输出顺序需要调整为:
1
'结束了'
2
根据打印结果我们很容易想到对策,即把语句 obj.foo++ 和语句 console.log('结束了') 位置互换即可。那么有没有什么办法能够在不调整代码的情况下实现需求呢?这时就需要响应系统支持调度
我们可以为 effect 函数设计一个选项参数 options,允许用户指定调度器:
effect(
() => {
console.log(obj.foo)
},
// options
{
// 调度器 scheduler 是一个函数
scheduler(fn) {
// ...
}
}
)
如上面的代码所示,用户在调用 effect 函数注册副作用函数时,可以传递第二个参数 options。它是一个对象,其中允许指定 scheduler 调度函数,同时在 effect 函数内部我们需要把 options 选项挂载到对应的副作用函数上:
function effect(fn, options = {}) {
const effectFn = () => {
cleanup(effectFn)
// 当调用 effect 注册副作用函数时,将副作用函数赋值给 activeEffect
activeEffect = effectFn
// 在调用副作用函数之前将当前副作用函数压栈
effectStack.push(effectFn)
fn()
// 在当前副作用函数执行完毕后,将当前副作用函数弹出栈,并把 activeEffect 还原为之前的值
effectStack.pop()
activeEffect = effectStack[effectStack.length - 1]
}
// 将 options 挂载到 effectFn 上
effectFn.options = options // 新增
// activeEffect.deps 用来存储所有与该副作用函数相关的依赖集合
effectFn.deps = []
// 执行副作用函数
effectFn()
}
有了调度函数,我们在 trigger 函数中触发副作用函数重新执行时,就可以直接调用用户传递的调度器函数,从而把控制权交给用户:
function trigger(target, key) {
const depsMap = bucket.get(target)
if (!depsMap) return
const effects = depsMap.get(key)
const effectsToRun = new Set()
effects && effects.forEach(effectFn => {
if (effectFn !== activeEffect) {
effectsToRun.add(effectFn)
}
})
effectsToRun.forEach(effectFn => {
// 如果一个副作用函数存在调度器,则调用该调度器,并将副作用函数作为参数传递
if (effectFn.options.scheduler) { // 新增
effectFn.options.scheduler(effectFn) // 新增
} else {
// 否则直接执行副作用函数(之前的默认行为)
effectFn() // 新增
}
})
}
如上面的代码所示,在 trigger 动作触发副作用函数执行时,我们优先判断该副作用函数是否存在调度器,如果存在,则直接调用调度器函数,并把当前副作用函数作为参数传递过去,由用户自己控制如何执行;否则保留之前的行为,即直接执行副作用函数。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入探讨了响应系统中调度执行的重要性以及实现方法。作者首先介绍了可调度性的概念,即在触发副作用函数重新执行时,有能力决定副作用函数执行的时机、次数以及方式。通过代码示例说明了如何通过调度器来控制副作用函数的执行顺序和次数。文章还提出了在调用effect函数注册副作用函数时,可以传递第二个参数options,允许用户指定调度器,从而实现对副作用函数执行的控制。此外,还介绍了如何通过调度器实现控制副作用函数的执行顺序和次数,以及实现计算属性computed和lazy的方法。通过这些方法,读者可以更好地理解响应系统中调度执行的重要性,并学习如何实现相应的功能。文章还探讨了watch函数的实现原理,以及如何实现通用的读取操作和自定义getter功能,使得watch函数更加强大。整体而言,本文深入浅出地介绍了响应系统中调度执行的重要性和实现方法,为读者提供了深入理解和应用的技术指导。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Vue.js 设计与实现》
立即购买
登录 后留言

精选留言

由作者筛选后的优质留言将会公开显示,欢迎踊跃留言。
收起评论
显示
设置
留言
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部