在使用 JS 去操作页面动画的场景下,如果使用 Vue 的数据响应式更新去做,会比直接使用原生 JS 操作($0.style.transform = 'xxx')更加耗时。因为 Vue 在数据更新后,不仅要更新视图,还要更新自身维护的虚拟dom节点,对新旧节点进行对比,再更新组件。

使用Vue操作动画:

<div id="box" :style="style"></div>
data() {
  return {
    translate: 0
  }
},
computed: {
  style() {
    return {
      transform: `translateX(${this.translate}px)`
    }
  }
},
methods: {
  go () {
    animate({
      targets: [[this.translate, 1000]],
      running: targets => {
        this.translate = targets[0]
      }
    })    
  }
}

每轮 requestAnimationFrame 都会去对比新旧节点,更新组件信息,消耗5.22ms,一轮总耗时9.91ms,其中5.22ms都是在处理 vue 的相关逻辑:

使用Vue操作动画

使用原生JS操作:

<div id="box"></div>
methods: {
  go () {
    const box = document.getElementById('box')
    animate({
      targets: [[0, 1000]],
      running: targets => {
        box.style.transform = `translateX(${targets[0]}px)`
      }
    })
  }
}

每一次 requestAnimationFrame 只耗时1.03ms,一轮总共耗时6.03ms:

原生JS操作

对比

最后的对比图,JS 执行时间原生操作快了将近一半:

原生

Vue

总结

在使用 Vue 的项目里,自然都会直接使用数据绑定来驱动视图更新,但如果是在操作动画的场景下,且对动画的性能有很高的要求,在修改动画的相关样式这一步可以改用原生操作。