網頁性能優化04-函數節流

函數節流(throttle)

1-函數節流介紹

  • 1.先理解什麼是js中的高頻事件
    • 高頻事件 : 觸發頻率極高的事件。例如 滾動條事件onscroll 鼠標移動onmousemove 網頁大小變化onresize等
      • 高頻觸發:事件本身不是高頻的,但是用戶可以通過很快的手速來觸發。例如用戶瘋狂快速點擊 搶購按鈕(onclick,onmousedown)

在這裏插入圖片描述

  • 2.高頻事件的危害

    • a.浪費資源,降低網頁速度,甚至導致瀏覽器卡死:由於高頻事件觸發非常頻繁,可能1秒鐘會執行幾十次甚至上百次,如果在這些函數內部,又調用了其他函數,尤其是操作了DOM (DOM操作耗性能且可能導致瀏覽器出現迴流) ,不僅僅會降低整個網頁的運行速度,甚至會造成瀏覽器卡死,崩潰。
    • b.網絡堵塞 : 如果在高頻事件中,進行了重複的ajax請求,可能會導致請求數據出現混亂,並且還佔用服務器帶寬增加服務器壓力 (間接增加服務器成本)
  • 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);
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章