js防抖和节流的深入讲解


Posted in Javascript onDecember 06, 2018

前言:

我们在做页面事件绑定的时候,经常要进行节流处理,比如鼠标异步点击,去执行一个异步请求时,需要让它在上一次没执行时不能再点击,又或者绑定滚动事件,这种持续触发进行dom判断的时候,就要按一定频率的执行。

本文主要给大家介绍了关于js防抖和节流的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧

0. 引入

首先举一个例子:

模拟在输入框输入后做ajax查询请求,没有加入防抖和节流的效果,这里附上完整可执行代码:

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <title>没有防抖</title>
 <style type="text/css"></style>
 <script type="text/javascript">
 window.onload = function () {
 //模拟ajax请求
 function ajax(content) {
 console.log('ajax request ' + content)
 }
 let inputNormal = document.getElementById('normal');

 inputNormal.addEventListener('keyup', function (e) {
 ajax(e.target.value)
 })
 }
 </script>
</head>

<body>
 <div>
 1.没有防抖的输入:
 <input type="text" name="normal" id="normal">
 </div>
</body>

</html>

效果:在输入框里输入一个,就会触发一次“ajax请求”(此处是console)。

js防抖和节流的深入讲解

没有防抖和节流

缺点:浪费请求资源,可以加入防抖和节流来优化一下。

本文会分别介绍什么是防抖和节流,它们的应用场景,和实现方式。防抖和节流都是为了解决短时间内大量触发某函数而导致的性能问题,比如触发频率过高导致的响应速度跟不上触发频率,出现延迟,假死或卡顿的现象。但二者应对的业务需求不一样,所以实现的原理也不一样,下面具体来看看吧。

1. 防抖(debounce)

1.1 什么是防抖

在事件被触发n秒后再执行回调函数,如果在这n秒内又被触发,则重新计时。

1.2 应用场景

(1) 用户在输入框中连续输入一串字符后,只会在输入完后去执行最后一次的查询ajax请求,这样可以有效减少请求次数,节约请求资源;

(2) window的resize、scroll事件,不断地调整浏览器的窗口大小、或者滚动时会触发对应事件,防抖让其只触发一次;

1.3 实现

还是上述列子,这里加入防抖来优化一下,完整代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <title>加入防抖</title>
 <style type="text/css"></style>
 <script type="text/javascript">
 window.onload = function () {
  //模拟ajax请求
  function ajax(content) {
  console.log('ajax request ' + content)
  }
  function debounce(fun, delay) {
  return function (args) {
   //获取函数的作用域和变量
   let that = this
   let _args = args
   //每次事件被触发,都会清除当前的timeer,然后重写设置超时调用
   clearTimeout(fun.id)
   fun.id = setTimeout(function () {
   fun.call(that, _args)
   }, delay)
  }
  }
  let inputDebounce = document.getElementById('debounce')
  let debounceAjax = debounce(ajax, 500)
  inputDebounce.addEventListener('keyup', function (e) {
  debounceAjax(e.target.value)
  })
 }
 </script>
</head>

<body>
 <div>
 2.加入防抖后的输入:
 <input type="text" name="debounce" id="debounce">
 </div>
</body>

</html>

代码说明:

1.每一次事件被触发,都会清除当前的 timer 然后重新设置超时调用,即重新计时。 这就会导致每一次高频事件都会取消前一次的超时调用,导致事件处理程序不能被触发;

2.只有当高频事件停止,最后一次事件触发的超时调用才能在delay时间后执行;

效果:

加入防抖后,当持续在输入框里输入时,并不会发送请求,只有当在指定时间间隔内没有再输入时,才会发送请求。如果先停止输入,但是在指定间隔内又输入,会重新触发计时。

js防抖和节流的深入讲解

加入防抖

2.节流(throttle)

2.1 什么是节流

规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。

2.2 应用场景

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

(2)在页面的无限加载场景下,需要用户在滚动页面时,每隔一段时间发一次 ajax 请求,而不是在用户停下滚动页面操作时才去请求数据;

(3)监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断;

2.3 实现

还是上述列子,这里加入节流来优化一下,完整代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <title>加入节流</title>
 <style type="text/css"></style>
 <script type="text/javascript">
 window.onload = function () {
  //模拟ajax请求
  function ajax(content) {
  console.log('ajax request ' + content)
  }

  function throttle(fun, delay) {
  let last, deferTimer
  return function (args) {
   let that = this;
   let _args = arguments;

   let now = +new Date();
   if (last && now < last + delay) {
   clearTimeout(deferTimer);
   deferTimer = setTimeout(function () {
    last = now;
    fun.apply(that, _args);
   }, delay)
   } else {
   last = now;
   fun.apply(that, _args);
   }
  }
  }
  let throttleAjax = throttle(ajax, 1000)
  let inputThrottle = document.getElementById('throttle')
  inputThrottle.addEventListener('keyup', function (e) {
  throttleAjax(e.target.value)
  })
 }
 </script>
</head>

<body>
 <div>
 3.加入节流后的输入:
 <input type="text" name="throttle" id="throttle">
 </div>
</body>

</html>

效果:实验可发现在持续输入时,会安装代码中的设定,每1秒执行一次ajax请求

js防抖和节流的深入讲解

加入节流

3. 小结

总结下防抖和节流的区别:

-- 效果:

函数防抖是某一段时间内只执行一次;而函数节流是间隔时间执行,不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数。

-- 原理:

防抖是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,都会清除当前的 timer 然后重新设置超时调用,即重新计时。这样一来,只有最后一次操作能被触发。

节流是通过判断是否到达一定时间来触发函数,若没到规定时间则使用计时器延后,而下一次事件则会重新设定计时器。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
javascript日期转换 时间戳转日期格式
Nov 05 Javascript
JavaScript中双叹号!!作用示例介绍
Sep 21 Javascript
jQuery中removeClass()方法用法实例
Jan 05 Javascript
JSON 数据详解及实例代码分析
Jan 20 Javascript
jQuery中Chosen三级联动功能实例代码
Mar 07 Javascript
微信小程序 实例开发总结
Apr 26 Javascript
Javascript防止图片拉伸的自适应处理方法
Dec 26 Javascript
JS 数组随机洗牌的实例代码
Sep 12 Javascript
vue强制刷新组件的方法示例
Feb 28 Javascript
详解Vue的mixin策略
Nov 19 Vue.js
关于JavaScript轮播图的实现
Nov 20 Javascript
vue中的可拖拽宽度div的实现示例
Apr 08 Vue.js
angular中两种表单的区别(响应式和模板驱动表单)
Dec 06 #Javascript
微信小程序dom操作的替代思路实例分析
Dec 06 #Javascript
详解Webstorm 下的Angular2.0开发之路(图文)
Dec 06 #Javascript
微信小程序实现通过js操作wxml的wxss属性示例
Dec 06 #Javascript
初探Vue3.0 中的一大亮点Proxy的使用
Dec 06 #Javascript
vue中v-for通过动态绑定class实现触发效果
Dec 06 #Javascript
vue通过指令(directives)实现点击空白处收起下拉框
Dec 06 #Javascript
You might like
PHP 和 XML: 使用expat函数(二)
2006/10/09 PHP
smarty 原来也不过如此~~呵呵
2006/11/25 PHP
php 在文件指定行插入数据的代码
2010/05/08 PHP
解密ThinkPHP3.1.2版本之模板继承
2014/06/19 PHP
codeigniter中view通过循环显示数组数据的方法
2015/03/20 PHP
javaScript对象和属性的创建方法
2007/01/15 Javascript
CSS JavaScript 实现菜单功能 改进版
2008/12/09 Javascript
基于jquery的内容循环滚动小模块(仿新浪微博未登录首页滚动微博显示)
2011/03/28 Javascript
js获取触发事件元素在整个网页中的绝对坐标(示例代码)
2013/12/13 Javascript
js截取中英文字符串、标点符号无乱码示例解读
2014/04/17 Javascript
鼠标移到图片上变大显示而不是放大镜效果
2014/06/15 Javascript
jquery中post方法用法实例
2014/10/21 Javascript
javascript操作字符串的原生方法
2014/12/22 Javascript
浅谈JavaScript中的字符编码转换问题
2015/07/07 Javascript
jQuery旋转木马式幻灯片轮播特效
2015/12/04 Javascript
Angular.js中ng-if、ng-show和ng-hide的区别介绍
2017/01/20 Javascript
Node.js Mongodb 密码特殊字符 @的解决方法
2017/04/11 Javascript
详解AngularJS用Interceptors来统一处理HTTP请求和响应
2017/06/08 Javascript
详述 Sublime Text 打开 GBK 格式中文乱码的解决方法
2017/10/26 Javascript
使用layer模态框给新页面传值的方法
2019/09/27 Javascript
json_decode 索引为数字时自动排序问题解决方法
2020/03/28 Javascript
使用Typescript和ES模块发布Node模块的方法
2020/05/25 Javascript
Js on及addEventListener原理用法区别解析
2020/07/11 Javascript
[59:30]VG vs LGD 2019国际邀请赛淘汰赛 胜者组 BO3 第二场 8.22
2019/09/05 DOTA
快速排序的算法思想及Python版快速排序的实现示例
2016/07/02 Python
Python增量循环删除MySQL表数据的方法
2016/09/23 Python
python 数据的清理行为实例详解
2017/07/12 Python
Python3查找列表中重复元素的个数的3种方法详解
2020/02/13 Python
基于Python的Jenkins的二次开发操作
2020/05/12 Python
pytorch加载自己的图像数据集实例
2020/07/07 Python
实例代码讲解Python 线程池
2020/08/24 Python
python解决OpenCV在读取显示图片的时候闪退的问题
2021/02/23 Python
幼儿园校车司机的岗位职责
2014/01/30 职场文书
幼儿园端午节活动总结
2015/05/05 职场文书
golang正则之命名分组方式
2021/04/25 Golang
HTML静态页面获取url参数和UserAgent的实现
2022/08/05 HTML / CSS