记一个Vue版本升级导致的bug——Vue的异步处理

前言

众所周知,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

排查

  1. 控制台未报错,排除代码逻辑错误;
  2. TSS 30102 之前该功能测试正常,TSS 30102 没有重保模块的需求,所以代码没有改动,排除代码修改的原因;
  3. 查看 vue-devtools 发现 isShowMoreTool 先改变为 true , 后又变为 false。现象就是 mouseover 和 mouseout 事件改变 isShowTool,watch 监听器函数执行,将菜单隐藏。
  4. 我知道 TSS 30102 中,因为引入 qaxd ,将 Vue 从 2.5 升级到了 2.6。切换不同版本 Vue 测试,果然和Vue 版本有关。

原因

  1. 子元素的显示隐藏会触发父元素的 mouseout、mouseover 事件。
  2. Vue 2.5 中,watch 监听器使用 macrotask 宏任务实现。
    1. 在子元素的 click 回调(isShowMoreTool === true)之后,菜单显示
    2. 触发mouseout(false)、mouseover (true)两个事件回调
    3. 之后再执行 watch 监听器,发现监听数据的值未发生改变(isShowTool === true),所以菜单如期望显示(isShowMoreTool === true)。
  3. Vue 2.6 中,watch 监听器使用 microtask 微任务实现。
    1. 在子元素的 click 回调(isShowMoreTool === true)之后,菜单显示
    2. 触发mouseout、watch
    3. 触发 mouseover、watch
    4. 执行完毕之后,菜单不显示 (isShowMoreTool === false)

解决方案

结合业务场景,修改 mouseover 为 mouseenter,修改 mouseout 为 mouseleave。子元素显示隐藏不会触发父元素mouseleave 事件。

Element: mouseenter event - Web APIs | MDN (mozilla.org)

image2021-12-21_17-26-2.png

你可能感兴趣的:(记一个Vue版本升级导致的bug——Vue的异步处理)