防抖(debounce)和节流(throttle)区别详细讲解及案例练习

一、防抖

1、概念

防抖策略(debounce):当事件被触发后,延迟 n 秒后再执行回调,;若在n秒内又被触发,则重新计时。

2、理解

多次触发只执行一次,比如王者荣耀回城,只有经过8秒才能触发回城,8秒途中再次触发回城或中断,都需要重新等待8秒才能回城

3、应用场景

登录、发短信等按钮避免用户点击太快,导致发送了多次请求,需要防抖。

4、封装防抖函数

let debounce = function (handler,delay) {
    let timer=null;
    return function () {
        if(timer) clearTimeout(timer);
        timer = setTimeout(()=>{
            fn.apply(this,arguments)
        },delay)
    }
}

二、节流

1、概念

在规定的时间范围内不会重复触发回调,只有大于这个时间间隔才会触发,把频繁触发变为少量触发。

2、理解

一个周期只执行一次,比如王者荣耀技能,只有经过技能冷却时间,,才能再次使用

3、应用场景

① 鼠标连续不断地触发某事件(如点击),只在单位时间内只触发一次;

② 懒加载时要监听计算滚动条的位置,但不必每次滑动都触发,可以降低计算的频率,而不必去浪费 CPU 资源;

③ 浏览器input搜索框展示下拉列表,需要节流,也可以使用防抖

4、封装节流函数

let throttle = function(handler,delay) {
	let timer = null;   
  	return function () {
       if(timer) return;
       timer = setTimeout(() => {
         fn.apply(this,arguments)
         timer = null
       })
   }
}

三、防抖与节流区别

名称区别举例
防抖最后一次执行的是防抖王者荣耀回城技能
节流控制次数的是节流英雄cd技能

通过对比防抖和节流函数,可以发现两者一个是return,一个是clearTimeout,为什么?
答:
防抖是触发间隔大于timer才会触发,所以每次在小于间隔time要清除定时器;

节流是不管time内触发多少次,只会每间隔time时间才会触发一次,所以用return

总结:防抖是限制操作,节流是减少操作

四、防抖与节流案例

1、正常页面

如果你在1秒内输入123,那它就会在1秒内分别执行输入1、2、3时的事件。

<!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>正常案例</title>
</head>

<body>
    <input type="text" id="input">
    <script>
        let input = document.getElementById("input");
        let span = document.createElement('span');
        let num = 0;
        input.addEventListener("input", inputEvent)
        //输入事件
        function inputEvent(e) {
            console.log(e, this)
            num++;//记录请求次数
            span.innerHTML = `<p>第${num}次请求了接口</p>`;
            document.body.appendChild(span);
        }
    </script>
</body>

</html>

2、防抖案例

如果在200ms内输入123,那它只会执行输入3时的事件。

<!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>防抖</title>
</head>

<body>
    <input type="text" id="input">
    <script>
        let input = document.getElementById("input");
        let span = document.createElement('span');
        let num = 0;
        input.addEventListener("input", debounce(inputEvent, 200))
        //输入事件
        function inputEvent(e) {
            console.log(e, this)
            num++;//记录请求次数
            span.innerHTML = `<p>第${num}次请求了接口</p>`;
            document.body.appendChild(span);
        }
        //防抖
        function debounce(fn, delay) {
            //这里相当于定义了一个全局的timer
            let timer = null;
            return function () {
                //如果定时器存在,那就清掉,开启新的计时器
                if (timer) {
                    clearTimeout(timer)
                }
                timer = setTimeout(() => {
                    fn.apply(this, arguments);
                }, delay);
            }
        }
    </script>
</body>

</html>

3、节流案例

如果你在一秒内输入123,那它只会执行输入1时的方法。

<!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>节流</title>
</head>
 
<body>
    <input type="text" id="input">
    <script>
        let input = document.getElementById("input");
        let span = document.createElement('span');
        let num = 0;
        input.addEventListener("input", throttle(inputEvent, 1000))
        //输入事件
        function inputEvent(e) {
            console.log(e, this)
            num++;//记录请求次数
            span.innerHTML = `<p>第${num}次请求了接口</p>`;
            document.body.appendChild(span);
        }
        //节流
        function throttle(fn, delay) {
            //相当于在全局定义了一个timer
            let timer = null;
            return function () {
                //如果timer存在,直接结束函数
                if (timer) {
                    return
                }
                timer = setTimeout(() => {
                    fn.apply(this, arguments);
                    //指定时间结束后,将timer变成null,否则这个函数将一直不执行
                    timer = null
                }, delay);
            }
        }
    </script>
</body>
 
</html>

五、插件

第三方插件库:lodash
地址:https://www.lodashjs.com/

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值