应用:
在咱们开发过程当中,会有一些用户操做,如滚动事件,输入事件等致使一直重复调用某函数,频率无限,使浏览器负担太重,致使页面卡顿。这时候就会用到防抖和节流来控制调用频率,减小浏览器负担。javascript
区别:
防抖:设置一个时间段A来作延时,在事件触发后A时间段内没有再次触发事件,那么函数会在A时间段事后自动执行一次;若是在还没到达A时间段,再次触发事件,那么会根据最后一次触发来从新计算A时间段,延时执行;以下图:css
节流:设置一个时间段B,在事件触发后,B时间后再次执行,无论用户触发多少遍事件,函数只会每隔B段时间执行一次;html
综上所述:防抖就是将无限次数变为最后一次执行,节流是将无限次数变为每隔一段时间执行;java
实现:
防抖(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):实现函数节流也有两种办法:时间戳和定时器;
时间戳方法:spa
<!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>
定时器:3d
<!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>
以上两种方式,都各有弊端,时间戳在最后一次触发后不执行函数,而定时器是第一次触发的时候没有当即执行函数,这两种方式没法完美的知足需求,因此咱们优化了一下节流方式,以下:code
<!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) { console.log(11) 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(function(){ i++; console.log(i+"次数"); startTime = Date.now(); }, 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>
时间戳+定时器版若有优化建议,欢迎提出!跪谢!