vue transition过渡动画---el.offsetWidth

707 阅读2分钟

使用vue中的过渡动画的时候:注意在使用javascript钩子的时候动画效果是无法出来的,得要额外的添加一句 el.offsetWidth

解释是这样的(非官方):

原因在于浏览器不会根据你js对style的修改实时更新,而一般是在当前js修改完毕之后,会对所有修改统一更新,而display:none(它本身是不能transition的)的状态切换影响了其他过渡效果的切换,毕竟为none的元素没法触发过渡。
将offsetWidth打开,你会发现过渡生效了,原因在于取offsetWidth导致浏览器重绘,使后面的style修改前,display确确实实变为了block,从而消除了元素状态为none对过渡的这种影响。添加setTimeout,“打断”js的执行也可生效

看看下面的代码,你觉得所有的动画都会执行吗?

  beforeEnter (el) {
    let top = this.state ? this.y : this.shopY
    let left = this.state ? this.x : this.shopX
    // 动画入场前,设置元素开始动画的起始位置
    el.style.width = this.width + 'px'
    el.style.height = this.height + 'px'
    el.style.position = 'fixed'
    el.style.left = left + 'px'
    el.style.top = top + 'px'
    // 动画过程禁止滚动
    document.getElementsByTagName('html')[0].style.overflowY = 'hidden'
    if (!this.state) {
      el.style.transform = `scale(0.1)`
      el.style.transformOrigin = '0 0'
      this.shopDom.classList.add(this.shopAnmationClass)
    }
  }
  // 设置完成动画之后的结束状态
  enter (el, done) {
    // el.offsetWidth // 强制刷新动画
    console.log(el.offsetWidth)
    // 结束位置
    let enterX = this.x - this.shopX
    let enterY = this.shopY - this.y
    // 这里要考虑enterX,enterY为负数的情况
    let x = this.state ? (enterX > 0 ? '-' + enterX : Math.abs(enterX)) : enterX
    let y = this.state ? enterY : (enterY > 0 ? '-' + enterY : Math.abs(enterX))
    let scaleNum = this.state ? '0.1' : '1'
    el.style.transform = `translate(${x}px,${y}px) scale(${scaleNum})`
    el.style.transformOrigin = '0 0'
    el.style.transition = 'all 1s ease'
    // 执行done函数,完成下面钩子函数
    setTimeout(() => {
      done()
    }, 800)
  }

这里直接使用 el.offsetWidth 会有个no-unused-expressions eslint 报错, 所以来个console.log(el.offsetWidth)eslint就不报错了。 这段代码是有问题的: 没有啦! 注意:done()这个回调函数,用于调用after-enter(after-leave) 中的逻辑,如果不需要可以不调用。本案例没有调用,所以就不展示了,当在leave中 使用了之后 动画过渡 就没了!

参考资料# 关于vue的transition中的几个钩子函数为什么没有产生动画