性能优化之防抖和节流

267 阅读1分钟

1.防抖(debounce)

作用:  高频率触发的事件,在指定的单位时间内,只响应最后一次,如果在指定的时间内再次触发,则重新计算时间。防抖类似于王者荣耀回城6秒,如果回城中被打断,再次回城需要再等6秒。

防抖怎么做?

<延迟>执行某件事, 会开个延时器, 等一会儿, 如果事件再次触发, 重开延时器, 直到一段时间内, 都没有触发了, 才执行

流程图.png

应用场景: 用户在输入框中连续输入一串字符时,可以通过防抖策略,只在输入完后,才执行查询的请求,这样可以有效减少请求次数,节约请求资源。

实现代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Document</title>
  <style>
    .box {
      width: 300px;
      height: 300px;
      background-color: #ccc;
      margin: 100px auto;
      text-align: center;
      color: #fff;
      font-size: 50px;
      align-self: center;
    }
  </style>
</head>
<body>
  <div class="box">0</div>
  <script>
    let count = 0
    // 为了在每次触发事件之后,都可以找到timeId,此时需要把timeId变成全局变量
    let timeId
    document.querySelector('.box').addEventListener('mousemove', function () {
      // 先关闭上一个延时器
      clearTimeout(timeId)
      // 开启一个新的延时器,时间到了之后就执行
      timeId = setTimeout(() => {
        this.innerHTML = ++count
      }, 500)

    })
  </script>
</body>
</html>

2.节流(throttle)

作用: 高频率触发的事件,在指定的单位时间内,只响应第一次。节流类似于游戏里的英雄平A,一定时间内点击多次只进行攻击一次。

节流怎么做?

<立刻>执行某件事, 但是事件执行的过程中, 关闭<节流阀>, 只有当事件执行完, 才能执行第二次

节流.png

应用场景: ① 鼠标连续不断地触发某事件(如点击),只在单位时间内只触发一次; ② 懒加载时要监听计算滚动条的位置,但不必每次滑动都触发,可以降低计算的频率,而不必去浪费 CPU 资源。

实现代码:

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Document</title>
  <style>
    .box {
      width: 300px;
      height: 300px;
      background-color: #ccc;
      margin: 100px auto;
      text-align: center;
      color: #fff;
      font-size: 50px;
      align-self: center;
    }
  </style>
</head>

<body>
  <div class="box">0</div>
  <script>
    // 用变量储存盒子内部的数字
    let count = 0
    // 用变量flag表示当前技能是否可以释放
    let flag = true
    // 鼠标在盒子内移动时,此时count++,并且渲染到页面
    document.querySelector('.box').addEventListener('mousemove', function () {
      // 一进来,首先先判断flag,看看能够释放技能
      if (flag) {
        // 如果能进来,表示可以释放技能
        this.innerHTML = ++count
        // 释放进之后,此时就不能再放了
        flag = false        
        // 进入冷却,冷却时间是500ms
        setTimeout(function () {
          // 如果时间到了,此时技能需要变成可以释放
          flag = true
        }, 500)
      }

    })
  </script>
</body>

3.意义

防抖和节流存在的意义: 都是为了性能优化, 可以阻止事件的频繁触发