js防抖和節(jié)流的深入講解
前言:
我們在做頁面事件綁定的時候,經常要進行節(jié)流處理,比如鼠標異步點擊,去執(zhí)行一個異步請求時,需要讓它在上一次沒執(zhí)行時不能再點擊,又或者綁定滾動事件,這種持續(xù)觸發(fā)進行dom判斷的時候,就要按一定頻率的執(zhí)行。
本文主要給大家介紹了關于js防抖和節(jié)流的相關內容,分享出來供大家參考學習,下面話不多說了,來一起看看詳細的介紹吧
0. 引入
首先舉一個例子:
模擬在輸入框輸入后做ajax查詢請求,沒有加入防抖和節(jié)流的效果,這里附上完整可執(zhí)行代碼:
<!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>
效果:在輸入框里輸入一個,就會觸發(fā)一次“ajax請求”(此處是console)。
沒有防抖和節(jié)流
缺點:浪費請求資源,可以加入防抖和節(jié)流來優(yōu)化一下。
本文會分別介紹什么是防抖和節(jié)流,它們的應用場景,和實現(xiàn)方式。防抖和節(jié)流都是為了解決短時間內大量觸發(fā)某函數而導致的性能問題,比如觸發(fā)頻率過高導致的響應速度跟不上觸發(fā)頻率,出現(xiàn)延遲,假死或卡頓的現(xiàn)象。但二者應對的業(yè)務需求不一樣,所以實現(xiàn)的原理也不一樣,下面具體來看看吧。
1. 防抖(debounce)
1.1 什么是防抖
在事件被觸發(fā)n秒后再執(zhí)行回調函數,如果在這n秒內又被觸發(fā),則重新計時。
1.2 應用場景
(1) 用戶在輸入框中連續(xù)輸入一串字符后,只會在輸入完后去執(zhí)行最后一次的查詢ajax請求,這樣可以有效減少請求次數,節(jié)約請求資源;
(2) window的resize、scroll事件,不斷地調整瀏覽器的窗口大小、或者滾動時會觸發(fā)對應事件,防抖讓其只觸發(fā)一次;
1.3 實現(xiàn)
還是上述列子,這里加入防抖來優(yōu)化一下,完整代碼如下:
<!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 //每次事件被觸發(fā),都會清除當前的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.每一次事件被觸發(fā),都會清除當前的 timer 然后重新設置超時調用,即重新計時。 這就會導致每一次高頻事件都會取消前一次的超時調用,導致事件處理程序不能被觸發(fā);
2.只有當高頻事件停止,最后一次事件觸發(fā)的超時調用才能在delay時間后執(zhí)行;
效果:
加入防抖后,當持續(xù)在輸入框里輸入時,并不會發(fā)送請求,只有當在指定時間間隔內沒有再輸入時,才會發(fā)送請求。如果先停止輸入,但是在指定間隔內又輸入,會重新觸發(fā)計時。
加入防抖
2.節(jié)流(throttle)
2.1 什么是節(jié)流
規(guī)定一個單位時間,在這個單位時間內,只能有一次觸發(fā)事件的回調函數執(zhí)行,如果在同一個單位時間內某事件被觸發(fā)多次,只有一次能生效。
2.2 應用場景
(1)鼠標連續(xù)不斷地觸發(fā)某事件(如點擊),只在單位時間內只觸發(fā)一次;
(2)在頁面的無限加載場景下,需要用戶在滾動頁面時,每隔一段時間發(fā)一次 ajax 請求,而不是在用戶停下滾動頁面操作時才去請求數據;
(3)監(jiān)聽滾動事件,比如是否滑到底部自動加載更多,用throttle來判斷;
2.3 實現(xiàn)
還是上述列子,這里加入節(jié)流來優(yōu)化一下,完整代碼如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>加入節(jié)流</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.加入節(jié)流后的輸入: <input type="text" name="throttle" id="throttle"> </div> </body> </html>
效果:實驗可發(fā)現(xiàn)在持續(xù)輸入時,會安裝代碼中的設定,每1秒執(zhí)行一次ajax請求
加入節(jié)流
3. 小結
總結下防抖和節(jié)流的區(qū)別:
-- 效果:
函數防抖是某一段時間內只執(zhí)行一次;而函數節(jié)流是間隔時間執(zhí)行,不管事件觸發(fā)有多頻繁,都會保證在規(guī)定時間內一定會執(zhí)行一次真正的事件處理函數。
-- 原理:
防抖是維護一個計時器,規(guī)定在delay時間后觸發(fā)函數,但是在delay時間內再次觸發(fā)的話,都會清除當前的 timer 然后重新設置超時調用,即重新計時。這樣一來,只有最后一次操作能被觸發(fā)。
節(jié)流是通過判斷是否到達一定時間來觸發(fā)函數,若沒到規(guī)定時間則使用計時器延后,而下一次事件則會重新設定計時器。
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關文章
JavaScript數據結構之雙向鏈表和雙向循環(huán)鏈表的實現(xiàn)
本篇文章主要介紹了JavaScript數據結構之雙向鏈表和雙向循環(huán)鏈表的實現(xiàn),具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-11-11JavaScript?error瀏覽器端錯誤捕獲處理方法筆記解決示例
這篇文章主要為大家介紹了JavaScript?error瀏覽器端錯誤捕獲處理方法筆記解決示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-06-06underscore之function_動力節(jié)點Java學院整理
因為underscore本來就是為了充分發(fā)揮JavaScript的函數式編程特性,所以也提供了大量JavaScript本身沒有的高階函數。本文重點給大家介紹underscore之function知識,感興趣的的朋友一起學習吧2017-07-07uniapp實現(xiàn)點擊出現(xiàn)彈窗功能實例
這篇文章主要給大家介紹了關于uniapp實現(xiàn)點擊出現(xiàn)彈窗功能的相關資料,UniApp框架中提供了兩種不同類型的彈出框,以幫助我們滿足不同的需求,需要的朋友可以參考下2023-08-08