防抖和节流的实现、区别与应用场景

2019-11-02 admin

应用: 在我们开发过程中,会有一些用户操作,如滚动事件,输入事件等导致一直重复调用某函数,频率无限,使浏览器负担过重,导致页面卡顿。这时候就会用到防抖和节流来控制调用频率,减少浏览器负担。

区别: 防抖:设置一个时间段A来做延时,在事件触发后A时间段内没有再次触发事件,那么函数会在A时间段过后自动执行一次;如果在还没到达A时间段,再次触发事件,那么会根据最后一次触发来重新计算A时间段,延时执行;如下图: 防抖.jpeg

节流:设置一个时间段B,在事件触发后,B时间后再次执行,不管用户触发多少遍事件,函数只会每隔B段时间执行一次; 节流.jpeg

综上所述:防抖就是将无限次数变为最后一次执行,节流是将无限次数变为每隔一段时间执行;


实现: **防抖(debounce):**防抖分为非立即执行与立即执行,非立即执行为触发后过一段时间才执行函数;立即执行为触发后马上执行函数,然后等待规定时间过后,再次触发有效,再次立即执行;

非立即执行:

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

<head>
 <meta charset="UTF-8">
 <title>加入防抖</title>
 <style type="text/css">
#box{width:500px;
height: 500px;
background: red;}
 </style>
</head>

<body>
 <div>
加入防抖后的输入:非立即执行
 <input type="text" name="debounce" id="debounce">
 <div id='box'>
在此移动
 </div>
 </div>
 <script type="text/javascript">
 // 防抖
 //非立即执行
 var i=0;
function debounce(fn, wait) { 
    console.log("执行")
    var timeout ; 
    return function(){
      if(timeout!== null) {
          clearTimeout(timeout)
        }
      timeout = setTimeout(fn,wait);    
    }
}
// 处理函数
function handle() {    
  i++;
   console.log(i+"次执行")
}
//触发事件 展示两种例子
//鼠标移动事件
 var box=document.getElementById('box');
 box.onmousemove=debounce(handle, 1000);
//键盘输入事件
var inp=document.getElementById('debounce');
inp.onkeyup=debounce(handle, 1000);
 </script>
</body>

</html>

立即执行:

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

<head>
 <meta charset="UTF-8">
 <title>加入防抖</title>
 <style type="text/css">
#box{width:500px;
height: 500px;
background: red;}
 </style>
</head>

<body>
 <div>
加入防抖后的输入:立即执行
 <input type="text" name="debounce" id="debounce">
 <div id='box'>
在此移动
 </div>
 </div>
 <script type="text/javascript">
 // 防抖
 //立即执行
 var i=0;
function debounce(fn, wait) { 
    var timeout ; 
    return function(){
      if(timeout!== null) {
          clearTimeout(timeout)
        }
      var flag=!timeout;
      timeout = setTimeout(function(){
        timeout=null;
      },wait);   
      if(flag){
        handle()
      } 
    }
}
// 处理函数
function handle() {    
  i++;
   console.log(i+"次执行")
}
//触发事件  展示两种例子
//鼠标移动事件
var box=document.getElementById('box');
 box.onmousemove=debounce(handle, 1000);
//键盘输入事件
var inp=document.getElementById('debounce');
inp.onkeyup=debounce(handle, 1000);
 </script>
</body>

</html>

**节流(throttle):**实现函数节流也有两种办法:时间戳和定时器; 时间戳方法:

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

<head>
 <meta charset="UTF-8">
 <title>加入防抖</title>
 <style type="text/css">
   #box{
     width:500px;
     height: 500px;
     background: red;
   }
 </style>
</head>
<body>
 <div>
    加入节流后的输入:时间戳
    <input type="text" name="debounce" id="inp">
    <div id='box'>
     在此移动
    </div>
 </div>
 <script type="text/javascript">
//节流
 var i=0;
var throttle = function(fn, way) {
    var prev = Date.now();
    return function() {
        var now = Date.now();
        if (now - prev >= way) {
            handle();
            prev = Date.now();
        }
    }
}
function handle() {
  i++;
    console.log(i+"次数");
}
//触发事件 展示两种例子
//鼠标移动事件
var box=document.getElementById('box');
 box.onmousemove=throttle(handle, 3000);
//键盘输入事件
var inp=document.getElementById('inp');
inp.onkeyup=throttle(handle, 3000);
</script>
</body>

</html>

定时器:

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

<head>
 <meta charset="UTF-8">
 <title>加入防抖</title>
 <style type="text/css">
#box{width:500px;
height: 500px;
background: red;}
 </style>
</head>

<body>
 <div>
加入节流后的输入:定时器
 <input type="text" name="debounce" id="inp">
 <div id='box'>
在此移动
 </div>
 </div>
 <script type="text/javascript">
 // 节流
 var i=0;
var throttle = function(fn, way) {
   var timer = null;
    return function() {
        if (!timer) {
            timer = setTimeout(function(){
              handle()
              timer=null;
            }, way);
        }
    }
}
function handle() {
  i++;
    console.log(i+"次数");
}
//触发事件 展示两种例子
//鼠标移动事件
var box=document.getElementById('box');
 box.onmousemove=throttle(handle, 2000);
//键盘输入事件
var inp=document.getElementById('inp');
inp.onkeyup=throttle(handle, 2000);
</script>
</body>
</html>

以上两种方式,都各有弊端,时间戳在最后一次触发后不执行函数,而定时器是第一次触发的时候没有立即执行函数,这两种方式无法完美的满足需求,所以我们优化了一下节流方式,如下:

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

<head>
 <meta charset="UTF-8">
 <title>加入防抖</title>
 <style type="text/css">
#box{width:500px;
height: 500px;
background: red;}
 </style>
</head>

<body>
 <div>
加入节流后的输入:定时器
 <input type="text" name="debounce" id="inp">
 <div id='box'>
在此移动
 </div>
 </div>
 <script type="text/javascript">
 // 节流
var i=0;
var throttle = function(fn, way) {
    var timer = null;
    var startTime = Date.now();
    return function() {
      var nowTime = Date.now();
      var remaining = way - (nowTime - startTime);  //剩余时间
      clearTimeout(timer);
      if (remaining <= 0) {      // 第一次触发立即执行
           handle()
          startTime = Date.now();
      } else {
        timer = setTimeout(handle, remaining);   //取消当前计数器并计算新的remaining
      }
    }
}
function handle() {
  i++;
    console.log(i+"次数");
}
//触发事件 展示两种例子
//鼠标移动事件
var box=document.getElementById('box');
 box.onmousemove=throttle(handle, 3000);
//键盘输入事件
var inp=document.getElementById('inp');
inp.onkeyup=throttle(handle, 3000);
 </script>
</body>

</html>

时间戳+定时器版有bug,请各位同猿指正错误,感谢!

[转载]原文链接:https://segmentfault.com/a/1190000020884558

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-78776.html

文章标题:防抖和节流的实现、区别与应用场景

相关文章
一些前端学习中好的书籍,整理
一、Javascript方面的书籍: 1 JavaScript权威指南(第6版):号称javascript圣经,前端必备;前端程序员学习核心JavaScript语言和由Web浏览器定义的JavaScript API的指南和综合参考手册; 2...
2015-11-12
js性能优化 如何更快速加载你的JavaScript页面
确保代码尽量简洁 不要什么都依赖JavaScript。不要编写重复性的脚本。要把JavaScript当作糖果工具,只是起到美化作用。别给你的网站添加大量的JavaScript代码。只有必要的时候用一下。只有确实能改善用户体验的时候用一下。 ...
2015-11-12
10个强大的纯CSS3动画案例分享
我们的网页外观主要由CSS控制,编写CSS代码可以任意改变我们的网页布局以及网页内容的样式。CSS3的出现,更是可以让网页增添了不少动画元素,让我们的网页变得更加生动有趣,并且更易于交互。本文分享了10个非常炫酷的CSS3动画案例,希望大家...
2015-11-16
Android中Okhttp3实现上传多张图片同时传递参数
之前上传图片都是直接将图片转化为io流传给服务器,没有用框架传图片。 最近做项目,打算换个方法上传图片。 Android发展到现在,Okhttp显得越来越重要,所以,这次我选择用Okhttp上传图片。 Okhttp目前已经更新到Okhttp...
2017-03-17
v-charts | 饿了么团队开源的基于 Vue 和 ECharts 的图表工具
在使用echarts生成图表时,经常需要做繁琐的数据类型转化、修改复杂的配置项,v-charts的出现正是为了解决这个 痛点。基于Vue2.0和echarts封装的v-charts图表组件,只需要统一提供一种对前后端都友好的数据格式 设置简...
2018-05-24
JavaScript实现PC手机端和嵌入式滑动拼图验证码三种效果
PC和手机端网站滑动拼图验证码效果源码,同时包涵了弹出式Demo,使用ajax形式提交二次验证码所需的验证结果值,嵌入式Demo,使用表单形式提交二次验证所需的验证结果值,移动端手动实现弹出式Demo三种效果 首先要确认前端使用页面,比如...
2017-03-17
Vue.js组件tab实现选项卡切换
本文实例为大家分享了vue插件tab选项卡的具体代码,供大家参考,具体内容如下 效果图: 代码如下: &lt;!DOCTYPE html&gt; &lt;html lang=&quot;en&quot;&gt; &lt;head&gt; ...
2017-03-13
Vue获取DOM元素样式和样式更改示例
在 vue 中用 document 获取 dom 节点进行节点样式更改的时候有可能会出现 ‘style’ is not definde的错误,这时候可以在 mounted 里用 $refs 来获取样式,并进行更改: &lt;template...
2017-03-13
从2014年的发展来展望JS的未来将会如何
&lt;font face=&quot;寰�杞�闆呴粦, Arial, sans-serif &quot;&gt;2014骞达紝杞�浠惰�屼笟鍙戝睍杩呴€燂紝鍚勭�嶈��瑷€灞傚嚭涓嶇┓锛屼互婊¤冻鐢ㄦ埛涓嶆柇鍙樺寲鐨勯渶姹傘€傝繖浜涜��...
2015-11-12
12个你未必知道的CSS小知识
虽然CSS并不是一种很复杂的技术,但就算你是一个使用CSS多年的高手,仍然会有很多CSS用法/属性/属性值你从来没使用过,甚至从来没听说过。 1.CSS的color属性并非只能用于文本显示 对于CSS的color属性,相信所有Web开发人员...
2015-11-12
回到顶部