4.8 立即执行的watch与回调执行时机
1、立即执行的watch
watch 的两个特性:一个是立即执行的回调函数,另一个是回调函数的执行时机。
立即执行的回调函数:
// 回调函数只有在响应式数据 obj 后续发生变化时才执行
watch(obj, () => {
console.log('变化了')
// 回调函数会在 watch 创建时立即执行一次
immediate: true
})
现在我们就要来完成这个功能:当 immediate 选项存在并且为 true 时,回调函数会在该watch 创建时立刻执行一次。所以我们可以把 scheduler 调度函数封装为一个通用函数,分别在初始化和变更时执行它。
// watch函数:传入参数source以及回调函数
function watch(source , cb) {
// 定义job,就是把scheduler的内容进行提取
const job = () => {
// 值发生改变会发生,此时就有新值了
newVal = effectFn()
// 回调函数,传入新旧值
cb(oldVal , newVal)
// 一定要记得更新旧值
oldVal = newVal
}
// 定义getter
let getter
if(typeof source === 'function'){
getter = source
}else {
getter = () => traverse(source)
}
// 定义新旧值
let newVal , oldVal
const effectFn = effect(
() => getter(),
{
lazy: true,
scheduler:job //改变的时候执行job
}
)
// 判断是否有immediate,有immediate就在最开始就要执行job
if(options.immediate){
// 执行job
job();
}else {
oldVal = effectFn();
}
// 调用effectFn就是旧值
oldVal = effectFn();
}
2、回调执行的时机
watch中flush 本质上是在指定调度函数的执行时机。当 flush 的值为 ‘post’ 时,代表调度函数需要将副作用函数放到一个微任务队列中,并等待 DOM 更新结束后再执行
// watch函数:传入参数source以及回调函数
function watch(source , cb) {
// 定义job,就是把scheduler的内容进行提取
const job = () => {
// 值发生改变会发生,此时就有新值了
newVal = effectFn()
// 回调函数,传入新旧值
cb(oldVal , newVal)
// 一定要记得更新旧值
oldVal = newVal
}
// 定义getter
let getter
if(typeof source === 'function'){
getter = source
}else {
getter = () => traverse(source)
}
// 定义新旧值
let newVal , oldVal
const effectFn = effect(
() => getter(),
{
lazy: true,
scheduler:() => {
if(options.flush === 'post'){
const p = Promise.resolve();
p.then(job);
}else {
job()
}
}
}
)
// 判断是否有immediate
if(options.immediate){
// 执行job
job();
}else {
oldVal = effectFn();
}
// 调用effectFn就是旧值
oldVal = effectFn();
}
在调度器函数内检测 options.flush 的值是否为 post,如果是,则将 job 函数放到微任务队列中,从而实现异步延迟执行;否则直接执行 job 函数,这本质上相当于 ‘sync’ 的实现机制,即同步执行。
之后很长一段时间我就不会看vue.js这本书啦,我的学长说现在市面上很多公司都改为react啦,react更加灵活,我之后会分享更多react的知识。