前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >前端高薪必会的JavaScript重难点知识:防抖与节流详解

前端高薪必会的JavaScript重难点知识:防抖与节流详解

原创
作者头像
艾编程
发布2022-12-14 23:09:49
1.5K0
发布2022-12-14 23:09:49
举报
文章被收录于专栏:艾编程艾编程

今天为大家带来一篇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。只需窗口调整完成后,计算窗口大小,防止重复渲染。

四、防抖函数的封装

代码语言:javascript
复制
<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 事件(单位时间只能发射一颗子弹) 防止高频点击提交,防止表单重复提交;

七、节流函数的封装

代码语言:javascript
复制
<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 实现 降低回调执行频率。节省计算资源

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、为什么需要防抖与节流
  • 二、防抖案例:搜索查询
  • 三、什么是防抖及应用场景
  • 四、防抖函数的封装
  • 五、节流案例:滚动加载更多
  • 六、什么是节流及应用场景
  • 七、节流函数的封装
  • 八、总结防抖与节流
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档