记一个Vue版本升级导致的bug——Vue的异步处理
2021-12-21 本文已影响0人
tian田小旺
前言
众所周知,Vue 在内部维护了一套异步任务队列。
仔细查看 Vue 的changelog 知道:
- 在 v2.4的时候,其使用 microtask 实现。
- 由于一些bug,在 v2.5 改为了使用 macrotask 实现。
- 又由于导致了得不偿失的bug,在 v2.6 Release v2.6.0 Macross · vuejs/vue (github.com) 改回使用 microtask 了。(details)
现象
点击【更多】不出现菜单了。
image2021-12-21_17-26-2.png image2021-12-21_17-26-49.png伪代码
image2021-12-21_17-40-51.png排查
- 控制台未报错,排除代码逻辑错误;
- TSS 30102 之前该功能测试正常,TSS 30102 没有重保模块的需求,所以代码没有改动,排除代码修改的原因;
- 查看 vue-devtools 发现 isShowMoreTool 先改变为 true , 后又变为 false。现象就是 mouseover 和 mouseout 事件改变 isShowTool,watch 监听器函数执行,将菜单隐藏。
- 我知道 TSS 30102 中,因为引入 qaxd ,将 Vue 从 2.5 升级到了 2.6。切换不同版本 Vue 测试,果然和Vue 版本有关。
原因
- 子元素的显示隐藏会触发父元素的 mouseout、mouseover 事件。
- Vue 2.5 中,watch 监听器使用 macrotask 宏任务实现。
- 在子元素的 click 回调(isShowMoreTool === true)之后,菜单显示
- 触发mouseout(false)、mouseover (true)两个事件回调
- 之后再执行 watch 监听器,发现监听数据的值未发生改变(isShowTool === true),所以菜单如期望显示(isShowMoreTool === true)。
- Vue 2.6 中,watch 监听器使用 microtask 微任务实现。
- 在子元素的 click 回调(isShowMoreTool === true)之后,菜单显示
- 触发mouseout、watch
- 触发 mouseover、watch
- 执行完毕之后,菜单不显示 (isShowMoreTool === false)
解决方案
结合业务场景,修改 mouseover 为 mouseenter,修改 mouseout 为 mouseleave。子元素显示隐藏不会触发父元素mouseleave 事件。
image2021-12-21_17-26-2.png