代码

  1. onMounted(() => {
  2. watchEffect(() => {
  3. const {width, left} = selectedDiv.value.getBoundingClientRect();
  4. indicator.value.style.width = width + 'px';
  5. const {left: containerLeft} = container.value.getBoundingClientRect();
  6. indicator.value.style.left = left - containerLeft + 'px';
  7. });
  8. });

目标效果

1.gif

实际效果

1.gif

解决思路

  • 这是一个开源项目,用户使用后发现 bug,但是在源文件和编译后都无 bug,猜想是 Vue3 对 watchEffect API 进行了改动。
  • 于是去查看 Vue3 官方文档,发现在 3.0.0-rc.13 版本中 watch API 使用 flush:'pre' 代替了flush:'post'

image.png

  • 文档中给出了解决办法,增加第二个参数 {flush:'post'} 以在 Vue 渲染更新之后触发回调,而不是之前。

    修复代码

    1. onMounted(() => {
    2. watchEffect(() => {
    3. const {width, left} = selectedDiv.value.getBoundingClientRect();
    4. indicator.value.style.width = width + 'px';
    5. const {left: containerLeft} = container.value.getBoundingClientRect();
    6. indicator.value.style.left = left - containerLeft + 'px';
    7. },{ flush: 'post' });
    8. });