js防抖与节流详讲

一、为什么需要防抖与节流

我们要了解什么是防抖与节流?这就需要回归到现实的应用场景来谈。

如果我们要监听浏览器滚动事件,或监听输入框值变化查询搜索结果等等,这些场景有个共同特点,频繁执行,然而我们不需要太频繁执行,比如滚动事件,间隔几百毫秒或者一秒执行回调就能满足业务需求,所以才有了节流和防抖的概念,目的是减少事件回调执行,提高浏览器性能。

接下来我们通过一个常见的防抖案例:搜索查询来展开讲解,帮助大家理解防抖。然后我们再通过一个常见的节流案例:滚动加载更多来展开讲解,帮助大家理解节流。

二、防抖案例:搜索查询

比如我们在一个表单中输入内容,JS通过监听输入框值的变化来查询搜索结果,我们会通过keyup事件来处理,当键盘弹起时就会触发keyup事件,在事件处理函数中发送请求处理查询结果。在我们输入内容时,会频繁的触发keyup事件,然而我们并不希望太频繁触发keyup事件处理函数发送请求查询。我们希望当我们抬起键盘间隔几百毫秒后再触发keyup事件处理函数发送请求查询(如果在间隔时间内再次触发keyup事件,就会把上一次的定时器清除,重新再计时)。因为频繁的触发增加了浏览器的性能消耗,同时也增加了对服务器的请求次数,增加服务器的压力。具体代码实现如下:

当我们以正常的速度在输入框中输入内容时,两种效果的前后对比

未添加防抖前的效效果

<body>
搜索查询:<input type="text" id="search" />
<script>
  const search = document.getElementById("search");
  var i = 0;
  search.onkeyup = function () {
      //处理查询内容....
      console.log(i++);//每触发一次,i+1
  };
</script>
</body>

添加防抖代码后的效果

<body>
搜索查询:<input type="text" id="search" />
<script>
  const search = document.getElementById("search");
  var i = 0;
  var timer = null;
  search.onkeyup = function () {
      //如果之前的定时器还在,则清除
      if (timer) {
          clearTimeout(timer);
      }
      //在400毫秒后再触发
      timer = setTimeout(function () {
           //处理查询内容...
          console.log(i++);
          timer = null; //本次查询完成,则定时器清除,以方便下次查询处理
      }, 400);
  };
</script>
</body>

每次键盘抬起都会触发keyup事件,但是keyup事件需要在400ms后才会处理查询操作,所以在下次触发keyup时,时间在400ms内,就会把上一次的定时器给清除了,本质上就没有触发查询操作。所以在所有电话号码输入完成后,400ms后就触发了一次查询操作。这样做的好处减少事件回调执行,提高浏览器性能。

三、什么是防抖及应用场景

防抖的概念

在连续的事件中,只需触发最后一次回调,也就是将几次操作合并为一此操作进行。原理是维护一个计时器,规定在delay(延迟)时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发。

应用场景

搜索框输入查询、手机号、邮箱验证输入检测。只需用户最后一次输入完,再发送请求

窗口大小resize。只需窗口调整完成后,计算窗口大小,防止重复渲染。

四、防抖函数的封装

<script>
   //fn为事件处理函数   delay延迟时间
   function debounce(fn, delay) {
       var timer = null;
       return function () {
           if (timer) {
               clearTimeout(timer);
          }
           timer = setTimeout(() => {
               fn.apply(this, arguments); //this和参数
               timer = null;
          }, delay);
      };
  }
</script>

五、节流案例:滚动加载更多

接下来我们通过滚动加载更多为案例来展开讲解,帮助大家理解节流。

当我们滚动浏览器的滚动条时,会频繁触发scroll事件。我们通过监听浏览器scroll事件来断判断滚动条位置,如果滚动条滚动到页面的最底部,则就会加载更多信息。因为滚动时会频繁触发scroll事件,就会造成频繁的判断滚动条位置。

而我们并不希望每次触发scroll事件都需要去判断滚动条的位置,来决定是否加载更多,我们希望能间隔一定时间(几百毫秒)再判断一次,然后决定是否加载更多。如果时间不够,啥处理也不做,这样就能减少浏览器性能的消耗。

滚动加载更多源理:

  • 可视区的高度 + 滚动条滚动高度 >=文档高度 (整个滚动高度) 时就触发加载更多信息

未添加节流处理前的效果

scroll事件函数中的代码,在scroll事件触发时会频繁的被执行,特别消耗性能

<script>
var i = 0;
window.onscroll = function () {
  //会频繁的处理以下代码,特别消耗性能
  console.log(++i);//测试被执行的次数
  var scrollTop = document.documentElement.scrollTop;
  var clientHeight = document.documentElement.clientHeight;
  var scrollHeight = document.documentElement.scrollHeight;
  if (scrollTop + clientHeight + 10 >= scrollHeight) {
      //满足以上条件,则加载更多数据
      console.log("开始加载更多数据....");
  }
};
</script>

添加节流处理后的效果

scroll事件中的代码,会在事件触发时,每隔100ms触发一次。

<script>
var i = 0;
var timer = null;
window.onscroll = function () {
  if (timer) {
      return;
  }
  timer = setTimeout(function () {
      console.log(++i);//测试被执行的次数
      var scrollTop = document.documentElement.scrollTop;
      var clientHeight = document.documentElement.clientHeight;
      var scrollHeight = document.documentElement.scrollHeight;
      if (scrollTop + clientHeight + 10 >= scrollHeight) {
          //满足以上条件,则加载更多数据
          console.log("开始加载更多数据....");
      }
      timer = null;
  }, 100);
};
</script>

同样的布局,同样的效果,在未做节流处理和做了节流处理,两者效果上有很大的差异。从头部滚动到底部触发加载更多,未做节流处理,共触发了35次代码的执行,而做了节流处理的,只触发了6次代码的执行。

滚动加载更多完整版案例代码,练习助理老师以及在钉钉群里获取-篇幅限制,放不下

六、什么是节流及应用场景

什么是节流

  • 使得一定时间内只触发一次函数。原理是通过判断是否到达一定时间来触发函数。

节流应用场景

  • 监听滚动事件判断是否到页面底部自动加载更多

  • 搜索联想功能

  • DOM元素的拖拽功能实现

  • 射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹)

  • 防止高频点击提交,防止表单重复提交;

七、节流函数的封装

<script>
   function throttle(fn, delay) {
       var timer = null;
       return function () {
           if (timer) {
               return;
          }
           timer = setTimeout(() => {
               fn.apply(this, arguments);//把this和参数传递过去
               timer = null;
          }, delay);
      };
  }
</script>

八、总结防抖与节流

不同点

  • 节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数

  • 防抖只是在最后一次事件后才触发一次函数。

应用场景

  • 防抖应用场景

  • 搜索框输入查询、手机号、邮箱验证输入检测。只需用户最后一次输入完,再发送请求

  • 窗口大小resize。只需窗口调整完成后,计算窗口大小,防止重复渲染。

  • 节流应用场景

  • 监听滚动事件判断是否到页面底部自动加载更多

  • 搜索联想功能

  • DOM元素的拖拽功能实现

  • 射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹)

  • 防止高频点击提交,防止表单重复提交;

相同点

  • 都可以通过使用 setTimeout 实现

  • 降低回调执行频率。节省计算资源

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值