js中如何实现防抖、节流?

  1. 节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效;
  2. 防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时

1、防抖

应用场景:

  1. scroll事件滚动触发
  2. 搜索框输入查询
  3. 表单验证
  4. 按钮提交事件
  5. 浏览器窗口缩放
  6. resize事件

正常情况:快速点击按钮,无论你点的有多快,只要点了一次,日志就会打印一次?

需求:在快速点击的过程中,如何只让最后一次能产生效果?

示例代码:

核心:

  1. 运用到定时器setTimeout()
  2. 每次点击需要清除上一次点击产生的定时器,保证最后一次点击产生的定时器才是有效可用的
<body>
<button class="button">点击</button>

<script type="text/javascript">
    <!--    防抖:用户点击=》多次点击会多次发送请求=》浪费性能-->
    //1、添加点击事件
    //2、添加防抖:1、定时器,2、高阶函数
    const button = document.querySelector('button');

    //防抖:在规定的时间点击一次
    button.addEventListener('click', debounce(change, 2000))

    //高阶函数:1、函数的返回值是一个函数或者参数是一个函数
    function debounce(fn, time=250) {
        let timer = null;//1、这个变量会保存在内存中,只会创建一次
        //用到定时器,规定的时间内只执行一次
        return function (e) {
            console.log("this", this);
            //判断定时器是否生成,如果生成了,清除上一次点击的定时器,保证只有最后一次点击的定时器才有用
            if (timer) {
                clearTimeout(timer);
            }

            let firstClick = !timer;
            //如果是第一次点击就立即执行
            if (firstClick) {
                //拿到外部函数的this,即按钮这个节点,将fn()函数的this指向
                fn.apply(this, arguments);//处理业务逻辑
            }
            timer = setTimeout(() => {
                timer = null;
            }, time)
        }
    }

    function change(e) {
        console.log(e);
    }
</script>
</body>

2、节流

应用场景:

  1. scroll:每隔一段时间计算位置信息
  2. 搜索框:实时搜索并发送请求,展示下拉列表

需求:如果你持续触发事件,每隔一段时间,只会执行一次事件

实现的两种方式:

1、定时器

核心:

  1. 运用到定时器setTimeout()
  2. 需要一个控制是否能够发送请求的阀门(节流阀)
<body>
<button class="button">点击</button>

<script type="text/javascript">
  	const button = document.querySelector('button');
    button.addEventListener('click', throttle(change, 2000));

    function change() {
        console.log("发送请求了...");
    }

    function throttle(fn, time=250) {
    
        /*注意这里用到了闭包*/
        let flag = true;//设置节流阀;这个变量会保存在内存中,只会创建一次
        return () => {
            if (flag) {
                flag = false;//flag值变为false
                //发起请求
                fn();
                //通过定时器,2s后将flag的值变为true,点击按钮才可再次发送请求
                setTimeout(() => {
                    flag = true
                }, time)
            }
        }
    }
</script>
</body>

2、时间戳

核心:

  • 获取触发事件时的时间戳,判断当前时间戳与初始时间戳是否大于执行间隔时间
<body>
<button class="button">点击</button>

<script type="text/javascript">
    const button = document.querySelector('button');
    button.addEventListener('click', throttle(change, 2000));

    function change() {
        console.log("发送请求了...");
    }

    function throttle(fn, time=250) {
    	/*注意这里用到了闭包*/
        let begin = 0;//设置时间戳
        return () => {
            //获取当前时间戳
            let date = new Date().getTime();
            //判断当前的时间戳与上一次点击的时间戳的差是否大于time
            if (date - begin > time) {
                fn();
                begin = date;
            }
        }
    }
</script>
</body>
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
防抖节流都是为了解决频繁触发事件时的性能问题。 防抖(Debounce):在某个时间段内,只执行一次事件。比如当用户不断输入搜索框时,不会立即执行搜索操作,而是等用户停止输入一段时间后再执行搜索操作,避免频繁发送请求。 节流(Throttle):在某个时间段内,多次事件只执行一次。比如当用户不断滚动页面时,不会每滚动一次就触发事件,而是等待一段时间后再执行,避免频繁触发事件。 具体代码实现如下: 防抖: ```javascript function debounce(fn, delay) { let timer = null; return function() { const context = this; const args = arguments; clearTimeout(timer); timer = setTimeout(function() { fn.apply(context, args); }, delay); } } // 使用方式 const searchFn = debounce(function() { // 搜索操作 }, 500); input.addEventListener('input', searchFn); ``` 节流: ```javascript function throttle(fn, delay) { let timer = null; let lastTime = 0; return function() { const context = this; const args = arguments; const now = +new Date(); if (now - lastTime > delay) { clearTimeout(timer); lastTime = now; fn.apply(context, args); } else { clearTimeout(timer); timer = setTimeout(function() { lastTime = now; fn.apply(context, args); }, delay - (now - lastTime)); } } } // 使用方式 const scrollFn = throttle(function() { // 滚动事件 }, 500); window.addEventListener('scroll', scrollFn); ``` 以上是基于函数的方式实现防抖节流,也可以使用 Lodash 等第三方库来实现

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值