三分钟带你轻松实现防抖

283 阅读2分钟

什么是防抖

防抖,顾名思义就是防止抖动,避免事件的重复触发

防抖的应用场景

我们使用网页时,经常会操作一些高频触发的事件,比如,用户正在使用搜索框输入关键字的时候,用户的每一次输入都会触发输入框的oninput事件,如果每次输入都向服务器发送请求来获取数据,会给服务器造成不必要的负载。而防抖就可以将一定时间内的多次触发合并为一次,只监听用户的最后一次输入,就只用向服务器发送一次请求,从而达到减少请求次数和服务器负载的效果。

防抖的设计思路

防抖的设计思路.png

防抖的代码实现

这里我用一个简单的小案例来演示防抖的具体写法

未设置防抖

在网页中生成一个盒子,并给盒子绑定鼠标移动事件,当鼠标在盒子内移动,盒子内的数字加1 动画.gif

<!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>
        .box {
            width: 500px;
            height: 500px;
            background-color: #ccc;
            color: #fff;
            text-align: center;
            font-size: 100px;
        }
    </style>
</head>

<body>
    <div class="box"></div>
    <script>
        // 获取dom元素
        const box = document.querySelector('.box')

        // 绑定事件
        box.addEventListener('mousemove', e => {
            // 业务代码:数字加1
            box.innerText++
        })
    </script>
</body>
</html>

可以看到,由于没有设置防抖,鼠标在盒子内的每一次移动都触发了数字加1的业务

设置防抖

根据我们上面防抖的设计思路,我们先将1秒的 延时器延时器id 设置好,再将业务代码放到延时器代码里面,如果事件多次触发,就使用 ClearTimeout(延时器id) 清除上一个延时器,再开启下一个延时器。 设置防抖.gif

<script>
        // 获取dom元素
        const box = document.querySelector('.box')

        // 设置延时器id
        let timeId

        // 绑定事件
        box.addEventListener('mousemove', e => {
            // 清除延时器
            clearTimeout(timeId)
            // 设置延时器1秒后触发
            timeId = setTimeout(() => {
                // 业务代码:数字加1
                box.innerText++
            }, 1000)
        })
    </script>

在设置防抖后,鼠标在盒子内的连续移动并不会触发数字加1的业务,而当鼠标停下时,在停下之前的 最后一次 移动则会触发数字加1,这样就实现了防抖的功能。

更多写法

我们除了使用js原生的延时器来实现防抖之外,还可以使用 Lodash工具库 来实现。Lodash 是一个一致性、模块化、高性能的 JavaScript 实用工具库。

在VS Code中引入js文件

<script src="lodash.js"></script>

再使用Lodash已经封装好的写法 _.debounce 来实现防抖。

 <script>
    // 获取dom元素
    const box = document.querySelector('.box')

    // 定义函数fn
    function fn() {
      // 业务代码:数字加1
      box.innerText++
    }
    // 声明变量newFn
    const newFn = _.debounce(fn, 1000)
    box.addEventListener('mousemove', newFn)
  </script>

另外还有一种更加简洁的写法

<script>
    // 获取dom元素
    const box = document.querySelector('.box')
    
    // 绑定事件的同时使用_.debounce方法
    box.addEventListener('mousemove', _.debounce(() => {
      box.innerText++
    }, 1000))

当然,简洁的代码往往会牺牲一些可读性,以上三种写法怎么选择,要根据实际工作需求来判断。

总结

当用户在一定时间内高频触发事件,可以使用防抖只监听最后一次触发,达到以降低服务器负载的目的。