利用防抖思想优化transitionend事件触发多次的问题

161 阅读1分钟

transitionend事件触发时机:在css过渡动画完成后触发

demo:鼠标移入时,将div变为蓝色,移出时,将div恢复成红色

    <style>
      div {
        width: 100px;
        height: 100px;
        background-color: red;
        transition: all 0.5s linear;
        margin: 100px auto;
      }
    </style>
    
    
    <div></div>
    <script>
      const div = document.querySelector('div')
      div.addEventListener('transitionend', () => {
        console.log('transitionend')
      })
 
      div.addEventListener('mouseenter', () => {
        div.style.background = 'blue'
      })

      div.addEventListener('mouseleave', () => {
        div.style.background = 'red'
      })
    </script>

在移入移出时,观察transitionend的表现为:每当动画结束时,就会触发一次

动画.gif

当鼠标移入移出时,如果改变的样式不是一个,而是多个,transitionend就会多次触发

      div.addEventListener('mouseenter', () => {
        div.style.background = 'blue'
        div.style.width = '120px'
        div.style.height = '120px'
      })

      div.addEventListener('mouseleave', () => {
        div.style.background = 'red'
        div.style.width = '100px'
        div.style.height = '100px'
      })

动画.gif

这是因为,每个css属性发生变化时,都会触发transitionend

如果我们想在这个事件回调中做一些处理,那么函数就会多次执行,这显然不符合期望,可以只用防抖进行优化

      div.addEventListener(
        'transitionend',
        debounce(() => {
          console.log('transitionend')
        }, 20)
      )
      
      function debounce(fn, delay) {
        var timer = null
        return function () {
          if (timer) clearTimeout(timer)
          var _this = this
          var _arguments = arguments
          timer = setTimeout(function () {
            fn.apply(_this, _arguments)
          }, delay)
        }
      }

动画.gif