1. 什么是防抖節(jié)流
- 防抖就是無論如何觸發(fā)事件,只在設定的n秒之后執(zhí)行時間,如果在n秒內再次觸發(fā)了事件,則重新計時
- 節(jié)流就是在設定的時間內只觸發(fā)一次
2. 區(qū)別
- 防抖以最后一次觸發(fā)為準,如果在設定的n秒內再次觸發(fā),則以新的事件時間為準
- 節(jié)流以第一次觸發(fā)為準,執(zhí)行第一次時間后,在設定的n秒內觸發(fā)都不會執(zhí)行
3. 如何實現(xiàn)
// 下面的代碼共用此綁定事件
function doSomething() {
console.log('input')
}
var input = document.getElementById('input')
// 防抖
input.oninput = throttle(doSomething, 5000, {
leading: false
})
// 節(jié)流
input.oninput = throttle(doSomething, 5000, {
leading: false
})
防抖
- 利用定時器
- 思路:
- 如果在設定的時間內觸發(fā),清除定時器重新計時
- 重新設定定時器,利用apply/call執(zhí)行函數(shù)
- 可以增加立刻執(zhí)行選項
function debounce(func, wait, immediate) {
var timeout, result;
return function () {
var context = this; // 解決event指向問題
var args = arguments; // 傳參
if (timeout) clearTimeout(timeout);
if (immediate) {
// 如果已經執(zhí)行過,不再執(zhí)行
var callNow = !timeout;
timeout = setTimeout(function(){
timeout = null;
}, wait)
if (callNow) result = func.apply(context, args) // 只有立刻執(zhí)行有返回值,使用settimeout執(zhí)行函數(shù),因為異步原因,result為undefined
} else { // 非立刻執(zhí)行保持原邏輯
timeout = setTimeout(function(){
func.apply(context, args)
}, wait);
}
return result;
}
}
節(jié)流
- 利用定時器或時間戳
- 總結:
- 時間戳方式:第一次進入立刻執(zhí)行;定時器:并不立刻執(zhí)行,在n秒之后執(zhí)行
- 時間戳:停止觸發(fā)了,就不執(zhí)行了,因為是根據(jù)觸發(fā)的時間去和上一次時間進行比較;定時器:停止觸發(fā)了,仍然會執(zhí)行
- 思路:
- 結合兩種方式的優(yōu)點,既能立刻執(zhí)行,停止觸發(fā)也能執(zhí)行最后一次
- 分兩種判斷邏輯:1. 時間戳 2. 定時器;定時器為空(第一次進入或定時器執(zhí)行完成后)時進入時間戳邏輯;其余是進入定時器邏輯
function throttle(fn, wait, options) {
var timeout = null, pre = 0;
var context,arg;
if (!options) options = {};
var throttled = function () {
context = this;
arg = arguments;
var now = +new Date();
if (!pre && options.leading === false) pre = now; // +++ 禁止立刻執(zhí)行,remaining > 0, 執(zhí)行定時器邏輯
var remaining = wait - (now - pre); // 計算還剩下多少時間執(zhí)行下一次方法
// 時間戳:立刻執(zhí)行,第一次進入remaining必小于0,因為wait-now
if (remaining <= 0) {
console.log('時間戳')
if (timeout) {
clearTimeout(timeout) // 第一次進入,清除定時器,為后面做準備
timeout = null
}
pre = now; // now時間賦值pre,頻繁觸發(fā)時,基本不會出現(xiàn)remaining <= 0,會走下面的邏輯
fn.apply(context, arg)
if (!timeout) context = arg = null; // +++ 不太明白,或許是手動清除內存?
} else if (!timeout && options.trailing !== false) { // +++ 增加options.trailing !== false判斷,停止觸發(fā)不設置定時器了
console.log('定時器')
timeout = setTimeout(function () {
pre = options.leading === false ? 0 : +new Date(); // +++ 如果需要禁止立刻執(zhí)行,需要重新將pre重置為0,避免進入時間戳邏輯
timeout = null;
fn.apply(context, arg)
if (!timeout) context = arg = null; // +++ 不太明白,或許是手動清除內存?
}, remaining)
}
}
throttled.cancel = function () {
clearTimeout(timeout)
pre = 0;
timeout = null
}
return throttled;
}
參考鏈接
- 防抖
- 節(jié)流
最后編輯于 :
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。