函數節流(throttle)
1-函數節流介紹
- 1.先理解什麼是js中的
高頻事件
高頻事件
: 觸發頻率極高的事件。例如滾動條事件onscroll
鼠標移動onmousemove
網頁大小變化onresize等
高頻觸發
:事件本身不是高頻的,但是用戶可以通過很快的手速來觸發。例如用戶瘋狂快速點擊 搶購按鈕(onclick,onmousedown)
-
2.高頻事件的危害
- a.
浪費資源,降低網頁速度
,甚至導致瀏覽器卡死:由於高頻事件觸發非常頻繁,可能1秒鐘會執行幾十次甚至上百次,如果在這些函數內部,又調用了其他函數,尤其是操作了DOM (DOM操作耗性能且可能導致瀏覽器出現迴流) ,不僅僅會降低整個網頁的運行速度,甚至會造成瀏覽器卡死,崩潰。 - b.
網絡堵塞
: 如果在高頻事件中,進行了重複的ajax請求,可能會導致請求數據出現混亂,並且還佔用服務器帶寬增加服務器壓力 (間接增加服務器成本)
- a.
-
3.函數節流介紹(throttle)
- 函數節流:限制事件處理函數的執行週期。
- 例如:鼠標點擊事件,限制0.5s內只能被觸發一次。 無論你點擊有多快,0.5s也只會執行一次。
- 函數節流:限制事件處理函數的執行週期。
2-函數節流解決思路
限制事件處理函數的執行週期
- 1.聲明變量 記錄上一次 觸發時間 (默認爲0,保證事件第一次無條件觸發)
- 2.觸發時間時:判斷現在的時間 和 上一次時間 的間隔是否大於
節流間隔
- 3.成功觸發後 : 將現在的時間 變成 下一次時間 的參考時間
- 現任女友已經結束了, 她已經成爲下一任女友 故事裏的 前任女友
//函數節流1 : 聲明變量記錄上一次事件觸發時間
var lastTime = 0;
//1.1 鼠標移動事件
var i = 0;
window.onmousemove = function () {
//函數節流2 : 判斷觸發時間間隔 (0.5秒 = 500ms)
var currentTime = new Date().getTime(); //當前時間
if (currentTime - lastTime > 500) {
//事件處理函數
i++;
console.log('鼠標移動事件被觸發' + i + '次');
//函數節流3 : 事件成功觸發之後,當前時間 成爲 下一次觸發間隔參考時間
//說人話:現任女友已經結束了, 她已經成爲下一任女友 故事裏的 前任女友
lastTime = currentTime;
};
};
3.萬能節流函數的封裝
- 爲什麼要封裝萬能的節流函數
- 在上一個小節中,我們的重點是介紹函數節流的思路。但是在實際開發中,每一個
節流函數的事件處理
都是不一樣的,他們可能是鼠標移入、鼠標移出、鼠標移動。 每一個案例需要的節流間隔
也不同
- 在上一個小節中,我們的重點是介紹函數節流的思路。但是在實際開發中,每一個
/**
* @description: 函數節流
* @param {type} fn: 事件處理函數
* @param {type} timeout: 節流間隔
* @return:
*/
function throttle(fn, timeout) {
/*核心技術介紹
1. 函數節流需要使用變量來存儲 上一次觸發時間
2. 這個變量如果是局部變量 : 則函數完畢會被回收。 如果是全局變量:則會造成全局變量污染
3.解決方案 : 利用函數本身也是對象,使用函數本身的靜態成員來存儲 上一次觸發時間
*/
//給throttle添加靜態成員lastTime
if(!throttle.lastTime){
/* 爲什麼一定要有這一步呢?
因爲函數對象的屬性不存在時,默認取值會得到undefined,而undefined在做數學計算
的時候會轉成number類型得到NaN. Number(undefined) 結果是NaN。無法計算
*/
throttle.lastTime = 0;
};
//1.記錄當前時間
var currentTime = new Date().getTime();
//2.判斷觸發時間間隔
if (currentTime - throttle.lastTime > timeout) {
fn();
//3.將當前時間作爲 下一次觸發時間 參考時間
throttle.lastTime = currentTime;
};
};
//1.2 滾動條事件
var j = 0;
window.onscroll = function () {
//節流函數 : 滾動條 0.5s 只會執行一次
throttle(function () {
j++;
console.log('滾動事件被觸發' + j + '次');
}, 500);
};
//2. 高頻觸發 :事件本身觸發不頻繁, 但是用戶可以通過瘋狂觸發來實現高頻
var btn = document.querySelector('#btn');
var p1 = document.querySelector('#p1');
var k = 0;
btn.onclick = function () {
//節流函數 : 按鈕1s 只能點擊一次
throttle(function () {
k++;
p1.innerText = '點擊事件被觸發' + k + '次';
}, 1000);
};