手撕代码——节流与防抖

欢迎大家来到手撕代码系列,本期介绍的是前端常见的节流与防抖的内容,包括节流与防抖的定义、它们的示例代码、它们常见的业务场景。如有错误,烦请各位大佬指正,主打一个听劝!

在开发中我们经常会遇到一些高频率事件,比如:鼠标移动,滑动窗口,键盘输入,按钮点击等等。无论是节流还是防抖,其实都是对于这种高频率事件的一种优化,如果我们的事件不需要那么高的触发频率,节流防抖是一种很好的性能优化方案。

节流

定义

节流是指在某个事件持续触发时,限制一定时间间隔只执行一次回调函数。

举个很生动的例子,就像游戏里面的普通攻击一样,无论你在一次普攻动作时间内点多少次普攻键,它都只会普攻一下。

业务场景

假设我们假设有一个按钮,点击一次就能造成页面上出现某些过渡效果,我们假设这个过渡动画为1s,此时我们不希望用户点击过快导致1s的动画还没结束就进入下一个动画,因此我们可以对这个过渡动画的回调函数进行节流处理。

示例代码

时间戳实现

以下这段节流代码是3s内只能触发一次回调函数,通过计算两个时间戳的差值来实现,当触发回调函数后又重新重置pretime,重新开始3s的节流处理。同时处理了send函数的this指向以及额外参数的问题。

注意:throttle函数会在第一次触发时就调用回调函数

html 复制代码
<body>
  <button id="btn">提交</button>
</body>

<script>
  function send(msg1,msg2) {
    console.log(msg1,msg2);
    console.log(this);
  }
  const btn = document.getElementById("btn");
  btn.addEventListener("click", throttle(send, 3000,'haha','hihi'));

  function throttle(fun, delay,...args) {
    let pretime = Date.now();
    return function () {
      if (Date.now() - pretime > delay) {
        //箭头函数,此时this就是指向btn
        fun.call(this, ...args); 
        // 如果调用成功重置pretime
        pretime = Date.now();
      }
    };
  }
</script>

定时器实现

这段代码通过定时器实现节流

注意:throttle2函数会时间到达后最后自动执行一次回调函数

html 复制代码
<body>
  <button id="btn">提交</button>
</body>

<script>
  function send(msg1,msg2) {
    console.log(msg1,msg2);
    console.log(this);
  }
  const btn = document.getElementById("btn");
  btn.addEventListener("click", throttle(send, 3000,'haha','hihi'));

  function throttle(fun, delay,...args) {
    let pretime = Date.now();
    return function () {
      if (Date.now() - pretime > delay) {
        //箭头函数,此时this就是指向btn
        fun.call(this, ...args); 
        // 如果调用成功重置pretime
        pretime = Date.now();
      }
    };
  }
</script>

防抖

定义

防抖指的是无论触发多少次事件,在事件触发最后一次后 n 秒后才执行。

就像游戏里面的回城一样,回城传送这个动作需要点击回城键几秒后才能实现,这几秒内如果我打断了回城这个动作那我就要重新开始计时。

业务场景

防抖最典型的业务场景就是搜索框了。当用户在搜索框内打字时,可能关键字还没有输入完毕,此时我们发送请求是无意义的,同时也会加重服务器的负担。于是我们通过防抖函数,设置为输入结束后0.5s才会发送请求 ,此时用户大概率输入完毕。

示例代码

定时器实现

防抖函数与上面节流函数定时器实现的不同在于每次被事件触发以后都会重置定时器进行计时。

js 复制代码
<body>
    <!-- 创建一个提交按钮 -->
    <button id="btn">提交</button> 
</body>
</html>
<script>
    function send(msg1,msg2){
        console.log(msg1,msg2,this);
        console.log('发送请求');
    }

    const btn = document.getElementById("btn");
    btn.addEventListener("click",debounce(send,1000,'hahah','ooo')) //给btn按钮绑定点击监听事件

    function debounce(fun,time,...args){
        let name
        return function(){
            if(name) clearInterval(name)
            name = setTimeout(() => {
                fun.call(this,...args)
            }, time);
        }
    }

</script>
相关推荐
想你的风吹到了瑞士4 分钟前
变量提升&函数提升
前端·javascript·vue.js
生椰拿铁You16 分钟前
12 —— Webpack中向前端注入环境变量
前端
Huazzi.43 分钟前
免费好用的静态网页托管平台全面对比介绍
前端·网络·github·web
吃土少女古拉拉1 小时前
前端和后端
前端·学习笔记
夫琅禾费米线1 小时前
leetcode2650. 设计可取消函数 generator和Promise
开发语言·javascript·leetcode·ecmascript
寒雒2 小时前
【Python】实战:实现GUI登录界面
开发语言·前端·python
独上归州2 小时前
Vue与React的Suspense组件对比
前端·vue.js·react.js·suspense
战族狼魂2 小时前
html+js实现图片的放大缩小等比缩放翻转,自动播放切换,顺逆时针旋转
javascript·css·html
Komorebi⁼2 小时前
Vue核心特性解析(内含实践项目:设置购物车)
前端·javascript·vue.js·html·html5
明月清风徐徐2 小时前
Vue实训---0-完成Vue开发环境的搭建
前端·javascript·vue.js