當用戶在網頁中進行操作時,如點擊、滾動、輸入等,往往會頻繁地觸發事件,如果每個事件都立即執行相應的函式,可能會導致性能問題和用戶體驗不佳,因為這些函式可能需要執行復雜的操作,如計算、網路請求等,
為了優化這種情況,我們可以使用防抖和節流來限制函式的呼叫次數,從而提高性能和用戶體驗,
防抖
防抖是指在一定的時間間隔內,將多次觸發的事件合并成一次執行,
防抖的實作思路是:每次事件被觸發時,設定一個計時器,在指定的時間間隔內,如果該事件被再次觸發,則清除計時器并重新開始計時,直到指定的時間間隔內沒有事件觸發為止,然后呼叫函式,
防抖可以用于處理一些頻繁觸發的事件,如視窗大小改變、輸入框輸入等,以下是一個簡單的防抖函式實作:
function debounce(fn, delay) { let timer; return function() { const context = this; const args = arguments; clearTimeout(timer); timer = setTimeout(function() { fn.apply(context, args); }, delay); }; }
這個函式接收兩個引數: fn 是要防抖的函式, delay 是防抖時間間隔,回傳一個新的函式,在防抖時間間隔內,重復呼叫這個新函式不會立即觸發原函式,只有等時間間隔過去之后才會觸發,
節流
節流是指在一定的時間間隔內,函式只被呼叫一次,如果在這個時間間隔內觸發了多次事件,只有第一次會呼叫函式,其余的會被忽略,
節流的實作思路是:每次事件被觸發時,如果函式沒有在指定的時間間隔內被呼叫過,則呼叫函式并設定一個計時器,在指定的時間間隔內不再觸發事件,如果在指定的時間間隔內再次觸發了事件,則不呼叫函式,直到指定的時間間隔過去,重新開始呼叫函式,
節流可以用于處理一些頻繁觸發的事件,如頁面滾動、滑鼠移動等,以下是一個簡單的節流函式實作:
function throttle(fn, delay) { let timer; return function() { const context = this; const args = arguments; if (!timer) { timer = setTimeout(function() { fn.apply(context, args); timer = null; }, delay); } }; }
這個函式接收兩個引數: fn 是要節流的函式, delay 是節流時間間隔,回傳一個新的函式,在指定的時間間隔內,只能呼叫一次原函式,
防抖和節流的實作方式可以有多種,具體實作應該根據實際場景進行調整,下面介紹一些常見的實作方式,
立即執行版和非立即執行版
防抖和節流的實作中,可以根據需求選擇立即執行版或非立即執行版,
立即執行版是指在每次觸發事件時,立即執行一次函式,然后在指定的時間間隔內不再執行,這種方式適合處理一些需要立即回應的事件,如按鈕點擊等,
以下是立即執行版的防抖函式實作:
function debounce(fn, delay, immediate) { let timer; return function() { const context = this; const args = arguments; if (immediate && !timer) { fn.apply(context, args); } clearTimeout(timer); timer = setTimeout(function() { if (!immediate) { fn.apply(context, args); } timer = null; }, delay); }; }
這個函式增加了一個引數 immediate ,用來指定是否立即執行函式,如果設定為 true ,則在觸發事件時立即執行函式;否則等待指定的時間間隔后再執行,
非立即執行版是指在事件停止觸發指定時間后才執行一次函式,這種方式適合處理一些連續觸發的事件,如輸入框輸入等,
以下是非立即執行版的防抖函式實作:
function debounce(fn, delay, immediate) { let timer; return function() { const context = this; const args = arguments; if (timer) { clearTimeout(timer); } if (immediate && !timer) { fn.apply(context, args); } timer = setTimeout(function() { if (!immediate) { fn.apply(context, args); } timer = null; }, delay); }; }
這個函式與立即執行版的實作相似,區別在于多了一個 if (timer) { clearTimeout(timer); } 判斷,如果計時器已經存在,則在重新設定計時器之前先清除之前的計時器,
時間戳版和定時器版
防抖和節流的實作中,可以根據需求選擇時間戳版或定時器版,
時間戳版是指在事件觸發后,記錄下當前的時間戳,并在下次事件觸發時再次記錄時間戳,在指定的時間間隔內,如果事件再次觸發,則更新時間戳,如果時間戳與當前時間的差值超過了指定的時間間隔,則執行函式,這種方式適合處理一些需要立即回應的事件,如按鈕點擊等,
以下是時間戳版的節流函式實作:
function throttle(fn, delay) { let last = 0; return function() { const context = this; const args = arguments; const now = +new Date(); if (now - last > delay) { fn.apply(context, args); last = now; } };
這個函式中, last 記錄上次執行函式的時間戳,每次事件觸發時,計算當前時間戳與上次執行函式的時間戳的差值,如果超過指定的時間間隔,則執行函式并更新 last ,
定時器版是指在事件觸發后,設定一個定時器,在指定的時間間隔內不再觸發事件,如果在指定的時間間隔內再次觸發了事件,則不執行函式,直到定時器到期后再次執行函式,這種方式適合處理一些連續觸發的事件,如頁面滾動、滑鼠移動等,
以下是定時器版的節流函式實作:
function throttle(fn, delay) { let timer; return function() { const context = this; const args = arguments; if (!timer) { timer = setTimeout(function() { fn.apply(context, args); timer = null; }, delay); } }; }
這個函式與之前介紹的非立即執行版的防抖函式實作類似,區別在于將 setTimeout 的時間間隔設定為指定的時間間隔,而不是事件觸發后的延遲時間,
防抖和節流的主要區別在于它們限制函式呼叫的方式不同,防抖是指在指定的時間間隔內將多次觸發的事件合并成一次執行,而節流是指在指定的時間間隔內,函式只被呼叫一次,同時,防抖和節流也有一些缺點,比如可能會導致事件回應延遲或事件被忽略等問題,因此,在實際使用中,需要根據場景進行權衡和選擇,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/551117.html
標籤:其他
上一篇:js 工具類
下一篇:返回列表
