應用:
在咱們開發過程當中,會有一些用戶操做,如滾動事件,輸入事件等致使一直重複調用某函數,頻率無限,使瀏覽器負擔太重,致使頁面卡頓。這時候就會用到防抖和節流來控制調用頻率,減小瀏覽器負擔。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>
時間戳+定時器版若有優化建議,歡迎提出!跪謝!