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教程
Jun 09 Javascript
PPK 谈 JavaScript 的 this 关键字 [翻译]
Sep 29 Javascript
js 获取Listbox选择的值的代码
Apr 15 Javascript
javascript中encodeURI和decodeURI方法使用介绍
May 06 Javascript
javascript创建函数的20种方式汇总
Jun 23 Javascript
jquery实现简单合拢与展开网页面板的方法
Sep 01 Javascript
jQuery-1.9.1源码分析系列(十)事件系统之事件包装
Nov 20 Javascript
Bootstrap中datetimepicker使用小结
Dec 28 Javascript
bootstrap动态添加面包屑(breadcrumb)及其响应事件的方法
May 25 Javascript
微信小程序实现弹出菜单功能
Jun 12 Javascript
layui 实现二级弹窗弹出之后 关闭一级弹窗的方法
Sep 18 Javascript
如何解决jQuery 和其他JS库的冲突
Jun 22 jQuery
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的字符串用法小结
2010/06/08 PHP
PHP数组对比函数,存在交集则返回真,否则返回假
2011/02/03 PHP
基于php split()函数的用法详解
2013/06/05 PHP
Drupal7中常用的数据库操作实例
2014/03/02 PHP
php验证session无效的解决方法
2014/11/04 PHP
PHP+MySQL之Insert Into数据插入用法分析
2015/09/27 PHP
JavaScript window.setTimeout() 的详细用法
2009/11/04 Javascript
JavaScript面向对象(极简主义法minimalist approach)
2012/07/17 Javascript
使用javascript实现监控视频播放并打印日志
2015/01/05 Javascript
jq实现左侧显示图片右侧文字滑动切换效果
2015/08/04 Javascript
如何解决ligerUI布局时Center中的Tab高度大小
2015/11/24 Javascript
javascript实现input file上传图片预览效果
2015/12/31 Javascript
AngularJs中 ng-repeat指令中实现含有自定义指令的动态html的方法
2017/01/19 Javascript
详解vue-cli本地环境API代理设置和解决跨域
2017/09/05 Javascript
ES6 系列之 Generator 的自动执行的方法示例
2018/10/19 Javascript
浅析微信扫码登录原理(小结)
2018/10/29 Javascript
通过实例了解JS执行上下文运行原理
2020/06/17 Javascript
八种Vue组件间通讯方式合集(推荐)
2020/08/18 Javascript
vue中路由跳转不计入history的操作
2020/09/21 Javascript
用Python的Flask框架结合MySQL写一个内存监控程序
2015/11/07 Python
win7下python3.6安装配置方法图文教程
2018/07/31 Python
python 实现二维字典的键值合并等函数
2019/12/06 Python
将tensorflow模型打包成PB文件及PB文件读取方式
2020/01/23 Python
python中urllib.request和requests的使用及区别详解
2020/05/05 Python
Python 如何调试程序崩溃错误
2020/08/03 Python
CSS3 创建网页动画实现弹跳球动效果
2018/10/30 HTML / CSS
Turnbull & Asser官网:英国皇室御用的顶级定制衬衫
2019/01/31 全球购物
Michael Kors香港官网:美国奢侈品品牌
2019/12/26 全球购物
Solaris操作系统的线程机制
2012/12/23 面试题
本科毕业生的求职信范文
2013/11/20 职场文书
给物业的表扬信
2014/01/21 职场文书
信息总监管理职责范本
2014/03/08 职场文书
2014新生大学四年计划书
2014/09/21 职场文书
2016年入党心得体会范文
2016/01/23 职场文书
学校2016年全国助残日活动总结
2016/04/01 职场文书
使用python绘制分组对比柱状图
2022/04/21 Python