在瀏覽器 DOM 事件裏面,有一些事件會隨着用戶的操作不間斷觸發。比如:重新調整瀏覽器窗口大小(resize),瀏覽器頁面滾動(scroll),鼠標移動(mousemove)。
也就是說用戶在觸發這些瀏覽器操作的時候,如果腳本里面綁定了對應的事件處理方法,這個方法就不停的觸發。而當事件處理比較複雜的時候瀏覽器不斷執行計算,從而導致瀏覽器性能降低甚至卡死,影響用戶體驗。
下面我們就針對這一情況做函數的節流處理(以weindow.scroll爲例)。
1、簡單實現(未用閉包)
var timer = null;
window.onscroll = function () {
clearTimeout(timer);
timer = setTimeout(function() {
console.log(new Date().getTime());
}, 200);
};
2、利用閉包進行改進var throttle = function (fn,delay) {
var timer = null;
return function () {
clearTimeout(timer);
timer = setTimeout(function() {
fn();
}, delay);
}
};
function testFn (){
console.log(new Date().getTime());
}
window.onscroll = throttle(testFn, 200);
3、利用函數的私有變量保存tIdfunction throttle (method,context,delay) {//context用來保存this指向
clearTimeout(method.tId);
method.tId = setTimeout(function () {
method.call(context);
},delay)
}
function testFn(){
console.log(new Date().getTime());
}
window.onscroll = throttle(testFn,null,100);
上面這些方法已經可以起到節流效果了,但是會有一個問題。就是當用戶不斷的出發scroll事件的時候,我們所需要執行的函數一次也不會執行,所以我們就需要設置一個最小觸發時間,接下來我們對throttle函數再次進行改進。
//fn執行函數 delay停止觸發事件多長時間後執行函數 minTime不斷觸發時強制執行時間
var throttle = function (fn,delay,minTime) {
var timer = null;
var starTime = null;
return function () {
var now = +new Date();
!starTime && (starTime = now);
if( minTime && now - starTime > minTime ) {
fn();
starTime = now;//將開始時間重置
}else{
clearTimeout(timer);
timer = setTimeout(function() {
fn();
starTime = null;
}, delay);
}
}
};
function testFn(){
console.log(new Date().getTime());
}
window.onscroll = throttle(testFn,200,300);
這樣只需要傳入minTime最小觸發時間就可以了。