petite-vue 组件的 mounted 回调发生在 nextTick() 任务之后
在使用 petite-vue 开发项目时,有一个列表视图,每个列表项是一个自定义组件。
在向列表视图的数组数据添加数据后,希望通过 EventBus 触发一个事件,让新的列表项组件 mounted 回调可以响应这个事件。
当使用 PetiteVue.nextTick()
传入回调函数来触发事件时,发现新的组件并没有响应该事件。通过调试,发现对 mounted 的调用发生在 nextTick() 回调函数之后。嵌套调用两次 PetiteVue.nextTick()
或者使用 setTimeout()
可以解决。
究其原因,是因为 petite-vue 是异步渲染 DOM 的。在当前任务循环的宏任务中修改响应式数据后,petite-vue 响应数据变化,将响应变化的行为,作为一个函数,通过 Promise 添加到当前任务循环的微任务队列尾部。该响应行为可能会修改 DOM,对 DOM 进行更新、移除或新建。对于要新建的 DOM,如果有对应的组件,会先实例化该组件,然后才创建DOM,之后又将回调该组件 mounted 函数的行为作为一个函数添加到当前事件循环的微任务队列尾部。
为什么不直接回调 mounted,让 mounted 回调在 nextTcik() 添加的任务之前执行,而是在 nextTcik() 添加的任务之后才执行呢?
这是考虑到 nextTcik() 添加的任务可能还会修改数据,从而影响 DOM。
在 nextTcik() 添加的任务之后执行,mounted 回调取得的 DOM 将是 vue 对数据变化响应后的修改的最终版本。
需要注意的是,petite-vue 只有 mounted 与 unmounted 两个生命周期回调,没有 created。
PetiteVue.nextTick()
也是通过 Promise 添加函数到当前任务循环的微任务队列尾部。
PetiteVue.nextTick()
在当前任务循环的宏任务中运行,它直接添加了一个微任务;petite-vue 响应数据变化的行为是一个微任务,在宏任务运行完毕后才运行,它添加的回调组件 mounted 的微任务肯定是在宏任务中添加的微任务之后。
这就是触发 EventBus 事件的行为发生在组件监听 EventBus 事件的行为之前的原因。
而在改变响应式数据后,嵌套调用两次 PetiteVue.nextTick()
,第一次调用发生在宏任务中,它添加一个微任务,这个微任务执行第二次 PetiteVue.nextTick()
,这次又添加一个微任务队列尾部,在新添加的微任务中触发 EventBus 事件。
回调组件 mounted 的微任务先被添加,触发 EventBus 事件的为微务后被添加,组件也就能响应 EventBus 事件了。
至于 setTimeout(),它将任务添加到宏任务队列,该宏任务会在之后的事件循环中执行。而回调组件 mounted 的微任务在当前事件循环执行,组件自然能响应 EventBus 事件。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战