Vue.js---立即执行的watch与回调执行时机
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}// 定义getterlet getter if(typeof source === 'function'){getter = source}else {getter = () => traverse(source)}// 定义新旧值let newVal , oldValconst effectFn = effect(() => getter(),{lazy: true,scheduler:job //改变的时候执行job})// 判断是否有immediate,有immediate就在最开始就要执行jobif(options.immediate){// 执行jobjob();}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}// 定义getterlet getter if(typeof source === 'function'){getter = source}else {getter = () => traverse(source)}// 定义新旧值let newVal , oldValconst effectFn = effect(() => getter(),{lazy: true,scheduler:() => {if(options.flush === 'post'){const p = Promise.resolve();p.then(job);}else {job()}}})// 判断是否有immediateif(options.immediate){// 执行jobjob();}else {oldVal = effectFn();}// 调用effectFn就是旧值oldVal = effectFn();}
在调度器函数内检测 options.flush 的值是否为 post,如果是,则将 job 函数放到微任务队列中,从而实现异步延迟执行;否则直接执行 job 函数,这本质上相当于 ‘sync’ 的实现机制,即同步执行。
之后很长一段时间我就不会看vue.js这本书啦,我的学长说现在市面上很多公司都改为react啦,react更加灵活,我之后会分享更多react的知识。