说说节流吧

68 阅读2分钟

什么是节流(throttle)

节流就是在一段时间之内,只能触发一个函数。如果在这一段时间之内多次触发这个函数也没有用,只能有一次生效。

简易版节流的实现

<!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>
      body {
        height: 2400px;
      }
    </style>
  </head>

  <body>
    <script>
      let flag = true
      window.onscroll = function () {
        // 现在开始实现节流
        if (flag) {
          setTimeout(() => {
            console.log('人类朋友')
            // 执行完之后需要记得将flag置回 true 不然后面触发该事件就再也不会执行事件对应的回调函数了
            flag = true
          }, 1000)
        }

        // 执行一个定时器之后就将 flag 置为 false 也就是在定时器规定的事件之内最多只能执行一次 onscroll 事件对应的回调函数
        flag = false
      }
    </script>
  </body>
</html>

解释

我滚动页面的时候会触发其对应onscroll事件的回调函数。首先定义一个全局变量flag。我将回调函数触发的条件定义为flag为真的情况。

最开始flag为真,满足if语句,执行定时器函数。这个时候需要注意,在定时器函数还在定时的期间,代码已经执行到下方的flag = false了,这代表什么?这代表后续再疯狂滚动页面也不会满足if (flag)了。直到什么时候满足?直到定时器函数计时完成,将flag重新置为true

下面封装一个节流函数

<!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>
      body {
        height: 2400px;
      }
    </style>
  </head>

  <body>
    <script>
      let throttle = function (fn, delay) {
        let flag = true
        return function () {
          // 现在开始实现节流
          if (flag) {
            setTimeout(() => {
              fn()
              // 执行完之后需要记得将flag置回 true 不然后面触发该事件就再也不会执行事件对应的回调函数了
              flag = true
            }, delay)
          }
          // 执行一个定时器之后就将 flag 置为 false 也就是在定时器规定的事件之内最多只能执行一次 onscroll 事件对应的回调函数
          flag = false
        }
      }

      window.onscroll = throttle(function () {
        console.log('hello')
      }, 1000)
    </script>
  </body>
</html>

解释

将第一版的函数作为函数throttle的返回值,将throttle函数执行后返回的匿名函数作为事件onscroll的回调函数,向throttle函数传入函数fn与定时事件delay即可。