節流與防抖函數封裝和使用
常見應用場景:
- window的 resize 和 scroll 事件;
- 文字輸入時的 keyup 事件;
- 元素拖拽、移動時的 mousemove 事件;
防抖: 將多次執行變為最后一次執行
- 定義:多次觸發事件后,事件處理函數只執行一次,並且是在觸發操作結束時執行
- 原理:對處理函數進行延時操作,若設定的延時到來之前,再次觸發事件,則清除上一次的延時操作定時器,重新定時。
/**
*防抖函數
*@param fn 事件觸發的操作
*@param delay 多少毫秒內連續觸發事件,不會執行
*@returns {Function}
*/
function debounce(fn, delay){
let timer = null; //借助閉包
return function(){
let context = this,
args = arguments;
timer && clearTimeout(timer);
timer = setTimeout(function(){
fn.apply(context, args);
},delay);
}
}
//使用
function showTop() {
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滾動條位置:' + scrollTop);
}
window.onscroll = debounce(showTop,200);
函數節流: 將多次執行變為每隔一段時間執行
- 定義:當持續觸發事件時,保證一定時間段內只調用一次事件處理函數。
- 原理:對處理函數進行延時操作,通過設定時間片,控制事件函數間斷性的觸發。
/**
* 節流函數
* @param fn 事件觸發的操作
* @param delay 間隔多少毫秒需要觸發一次事件
*/
//基本原理
function throttle(fn, delay) {
let valid = true;
return function() {
let context = this;
let args = arguments;
if (!valid) {
return;
}
valid = false;
setTimeout(() => {
fn.apply(context, args);
valid = true;
}, delay);
}
}
//時間戳
function throttle1(fn, delay) {
let prev = new Date();
return function() {
let context = this;
let args = arguments;
let now = new Date();
if (now - prev >= delay) {
fn.apply(context, args);
prev = new Date();
}
}
}
//定時器
function throttle2(fn, delay) {
let timer = null;
return function() {
let context = this;
let args = arguments;
if (!timer) {
timer = setTimeout(function() {
fn.apply(context, args);
clearTimeout(timer);
}, delay)
}
}
}
//使用
function showTop() {
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滾動條位置:' + scrollTop);
}
window.onscroll = throttle(showTop,200);