javascript
JS中的防抖跟节流(DebounceThrottle)
前言:
在進行窗口的resize、scroll或輸入框的change、click等事件,輸入框內容校驗等操作時,如果事件處理函數調用的頻率無限制,會加重瀏覽器的負擔,導致用戶體驗非常糟糕。此時我們可以采用debounce(防抖)和throttle(節(jié)流)的方式來減少調用頻率,同時又不影響實際效果。
函數防抖(debounce):
當持續(xù)觸發(fā)事件時,一定時間段內沒有再觸發(fā)事件,事件處理函數才會執(zhí)行一次,如果設定的時間到來之前,又一次觸發(fā)了事件,就重新開始延時。如下圖,持續(xù)觸發(fā)click事件時,并不執(zhí)行debounce函數,當1000毫秒內沒有觸發(fā)click事件時,才會延時觸發(fā)click事件。
代碼示例:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>防抖</title> </head> <body><button id="debounce">點我防抖!</button><script>window.onload = function() {// 1、獲取這個按鈕,并綁定事件var myDebounce = document.getElementById("debounce");myDebounce.addEventListener("click", debounce(sayDebounce));}// 2、防抖功能函數,接受傳參function debounce(fn) {// 4、創(chuàng)建一個標記用來存放定時器的返回值let timeout = null;return function() {// 5、每次當用戶點擊/輸入的時候,把前一個定時器清除clearTimeout(timeout);// 6、然后創(chuàng)建一個新的 setTimeout,// 這樣就能保證點擊按鈕后的 interval 間隔內// 如果用戶還點擊了的話,就不會執(zhí)行 fn 函數timeout = setTimeout(() => {fn.call(this, arguments);}, 1000);};}// 3、需要進行防抖的事件處理function sayDebounce() {// ... 有些需要防抖的工作,在這里執(zhí)行console.log("防抖成功!");}</script> </body> </html>防抖效果
當持續(xù)觸發(fā)click事件時,事件處理函數debounce只在停止點擊1000毫秒之后才會調用一次,也就是說在持續(xù)觸發(fā)click事件的過程中,事件處理函數debounce一直沒有執(zhí)行。
函數節(jié)流(throttle):
當持續(xù)觸發(fā)事件時,保證一定時間段內只調用一次事件處理函數。節(jié)流通俗解釋就比如我們水龍頭放水,閥門一打開,水嘩嘩的往下流,秉著勤儉節(jié)約的優(yōu)良傳統(tǒng)美德,我們要把水龍頭關小點,最好是如我們心意按照一定規(guī)律在某個時間間隔內一滴一滴的往下滴。如下圖,持續(xù)觸發(fā)click事件時,并不立即執(zhí)行handle函數,每隔1000毫秒才會執(zhí)行一次throttle函數。
代碼示例:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>節(jié)流</title> </head> <body><button id="throttle">點我節(jié)流!</button><script>window.onload = function() {// 1、獲取按鈕,綁定點擊事件var myThrottle = document.getElementById("throttle");myThrottle.addEventListener("click", throttle(sayThrottle));}// 2、節(jié)流函數體function throttle(fn) {// 4、通過閉包保存一個標記let canRun = true;return function() {// 5、在函數開頭判斷標志是否為 true,不為 true 則中斷函數if(!canRun) {return;}// 6、將 canRun 設置為 false,防止執(zhí)行之前再被執(zhí)行canRun = false;// 7、定時器setTimeout( () => {fn.call(this, arguments);// 8、執(zhí)行完事件(比如調用完接口)之后,重新將這個標志設置為 truecanRun = true;}, 1000);};}// 3、需要節(jié)流的事件function sayThrottle() {console.log("節(jié)流成功!");}</script> </body> </html>節(jié)流效果
當持續(xù)觸發(fā)click事件時,事件處理函數throttle只在1000毫秒間隔之后才會調用一次,也就是說在持續(xù)觸發(fā)click事件的過程中,事件處理函數debounce只會在指定時間間隔內執(zhí)行一次任務。
總結:
- 防抖:任務頻繁觸發(fā)的情況下,只有任務觸發(fā)的間隔超過指定間隔的時候,任務才會執(zhí)行。原理是維護一個計時器,規(guī)定在delay時間后觸發(fā)函數,但是在delay時間內再次觸發(fā)的話,就會取消之前的計時器而重新設置。這樣一來,只有最后一次操作能被觸發(fā)。
場景示例:有個輸入框,輸入之后會調用接口,獲取聯(lián)想詞。但是,因為頻繁調用接口不太好,所以我們在代碼中使用防抖功能,只有在用戶輸入完畢的一段時間后,才會調用接口,出現聯(lián)想詞。
- 節(jié)流:任務頻繁觸發(fā)的情況下,指定時間間隔內只會執(zhí)行一次任務。原理是通過判斷是否到達一定時間來觸發(fā)函數
場景示例:懶加載要監(jiān)聽計算滾動條的位置,使用節(jié)流按一定時間的頻率獲取
- 區(qū)別:?函數節(jié)流不管事件觸發(fā)有多頻繁,都會保證在規(guī)定時間內一定會執(zhí)行一次真正的事件處理函數,而函數防抖只是在最后一次事件后才觸發(fā)一次函數。 比如在頁面的無限加載場景下,我們需要用戶在滾動頁面時,每隔一段時間發(fā)一次 Ajax 請求,而不是在用戶停下滾動頁面操作時才去請求數據。這樣的場景,就適合用節(jié)流技術來實現。
總結
以上是生活随笔為你收集整理的JS中的防抖跟节流(DebounceThrottle)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 文言文能编程了,是噱头还是突破?
- 下一篇: NYOJ 171 聪明的kk