Mounted中改变style属性的问题

image image 我在mounted里面动态改变progressStyle的样式,transition动画不执行

所以你都改了什么啊

height原来不是设置是0px吗?我在mounted里面设置progressStyle的height为一个值,transition动画不执行,但是我setTimeout里面更改progressStyle的height值,transition动画执行

状态更新被合并了,渲染引擎压根儿就没得到执行过渡的时机。用 nextTick,或者就保持使用 setTimeout,让对 height 的更新在下一周期进行。

nextTick我用了,没用

是不是视图更新只是数据的更新就执行nextTick了,但是样式还没渲染,导致nextTick失效

nextTick 没有失效,反而是 nextTick 执行的太快,导致 CSS 引擎跟不上节奏……用 requestAnimationFrame 吧,这样就按显卡的规矩办事了。

这个问题我认为应该跟 js 的 event loop 有关:

  • 首先,我测了一下,页面的渲染是在第一次事件循环后才会执行;
<!-- 可以用这段代码测试一下,微任务执行完成之后,页面才会渲染 -->
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    #box {
      width: 100px;
      height: 100px;
      background-color: yellow;
    }
  </style>
</head>

<body>
  <div id="box">

  </div>
  <script>
    new Promise((resolve, reject) => {
      resolve()
    }).then(() => {
      let start = Date.now();
      while ((Date.now() - start) < 10000);
      console.log(111)
    })
  </script>
</body>

</html>
  • vue 中 $nextTick 在新的 chrome 版本中是采用 promise 方案执行,而既然是 Promise,那么其中的回调会被推入 micro queue 等待执行,也就是会在第一次事件循环时执行,这个时候还没有渲染页面;(第一次渲染是没有过渡效果的)
  • setTimeout 之所以有效,因为其回调会被推入 macro queue 中等待执行,当它执行时,已经是第二次事件循环了,页面这时已经渲染过了,这时再去更改 dom 样式,就会触发样式过渡效果;
1 Like