91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript節流與防抖實例分析

發布時間:2022-04-06 11:01:22 來源:億速云 閱讀:139 作者:iii 欄目:開發技術

本篇內容主要講解“JavaScript節流與防抖實例分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“JavaScript節流與防抖實例分析”吧!

    一、js防抖和節流

    在進行窗口的resize、scroll、輸出框內容校驗等操縱的時候,如果事件處理函數調用的頻率無限制,會加重瀏覽器的負擔,導致用戶體驗非常之差。那么為了前端性能的優化也為了用戶更好的體驗,就可以采用防抖(debounce)和節流(throttle)的方式來到達這種效果,減少調用的頻率。

    二、為什么滾動scroll、窗口resize等事件需要優化

    滾動事件的應用很頻繁:圖片懶加載、下滑自動加載數據、側邊浮動導航欄等。

    在綁定scroll、resize事件時,但它發生的時候,它被觸發的頻率非常高,間隔很近。在日常開發的頁面中,事件中涉及到的大量的位置計算、DOM操作、元素重繪等等這些都無法在下一個scroll事件出發前完成的情況下,瀏覽器會卡幀。

    三、滾動和頁面渲染前端性能優化的關系

    為什么滾動需要優化?前面提到了事件中涉及到大量的位置計算、DOM操作、元素重繪等等,這些又與頁面的渲染有關系,頁面渲染又與前端的性能優化有關系?套娃一樣,一層套著一層,每一層都聯系緊密,每一層都如此平凡且重要。

    review一下前端的渲染和優化

    網頁生成的時候,至少會渲染(Layout+Paint)一次。用戶訪問的過程中,還會不斷重新的重排(reflow)和重繪(repaint),用戶scroll行為和resize行為會導致頁面不斷的進行重新渲染,而且間隔頻繁,容易造成瀏覽器卡幀。

    四、防抖Debounce

    1 防抖Debounce情景

    ①有些場景事件觸發的頻率過高(mousemove onkeydown onkeyup onscroll)

    ②回調函數執行的頻率過高也會有卡頓現象。 可以一段時間過后進行觸發去除無用操作

    2 防抖原理

    一定在事件觸發 n 秒后才執行,如果在一個事件觸發的 n 秒內又觸發了這個事件,以新的事件的時間為準,n 秒后才執行,等觸發事件 n 秒內不再觸發事件才執行。

    官方解釋:當持續觸發事件時,一定時間段內沒有再觸發事件,事件處理函數才會執行一次,如果設定的時間到來之前,又一次觸發了事件,就重新開始延時。

    3 防抖函數簡單實現

        //簡單的防抖函數
        function debounce(func, wait, immediate) {
            //定時器變量
            var timeout;
            return function () {
                //每次觸發scrolle,先清除定時器
                clearTimeout(timeout);
                //指定多少秒后觸發事件操作handler
                timeout = setTimeout(func, wait);
            };
        };
        //綁定在scrolle事件上的handler
        function handlerFunc() {
            console.log('Success');
        }
        //沒采用防抖動
        window.addEventListener('scroll', handlerFunc);
        //采用防抖動
        window.addEventListener('scrolle', debounce(handlerFunc, 1000));

    4 防抖函數的演化過程

    ①this event綁定問題
        //以閉包的形式返回一個函數,內部解決了this指向的問題,event對象傳遞的問題
        function debounce(func, wait) {
            var timeout;
            return function () {
                var context = this;
                var args = arguments;
                clearTimeout(timeout)
                timeout = setTimeout(function () {
                    func.apply(context, args)
                }, wait);
            };
        };
    ②立即觸發問題
        //首次觸發執行,再次觸發以后開始執行防抖函數
        //使用的時候不用重復執行這個函數,本身返回的函數才具有防抖功能
    function debounce(func, wait, immediate) {
        var timeout;
        return function () {
            var context = this;
            var args = arguments;
            
            if(timeout) clearTimeout(timeout);
            // 是否在某一批事件中首次執行
            if (immediate) {
                var callNow = !timeout;
                timeout = setTimeout(function() {
                    timeout = null;
                    func.apply(context, args)
                    immediate = true;
                }, wait);
                if (callNow) {
                    func.apply(context, args)
                }
                immediate = false;
            } else {
                timeout = setTimeout(function() {
                    func.apply(context, args);
                    immediate = true;
                }, wait);
            }
        }
    }
    ③返回值問題
    function debounce(func, wait, immediate) {
        var timeout, result;
        return function () {
            var context = this, args = arguments;
            if (timeout)  clearTimeout(timeout);
            if (immediate) {
                var callNow = !timeout;
                timeout = setTimeout(function() {
                    result = func.apply(context, args)
                }, wait);
                if (callNow) result = func.apply(context, args);
            } else {
                timeout = setTimeout(function() {
                    result = func.apply(context, args)
                }, wait);
            }
            return result;
        }
    }
    ④取消防抖,添加cancel方法
    function debounce(func, wait, immediate) {
        var timeout, result;
        function debounced () {
            var context = this, args = arguments;
            if (timeout)  clearTimeout(timeout);
            if (immediate) {
                var callNow = !timeout;
                timeout = setTimeout(function() {
                    result = func.apply(context, args)
                }, wait);
                if (callNow) result = func.apply(context, args);
            } else {
                timeout = setTimeout(function() {
                    result = func.apply(context, args)
                }, wait);
            }
            return result;
        }
        debounced.cancel = function(){
            cleatTimeout(timeout);
            timeout = null;
        }
        return debounced;
    }

    五、節流Throttle

    1 節流Throttle情景

    ①圖片懶加載

    ②ajax數據請求加載

    2 節流原理

    如果持續觸發事件,每隔一段時間只執行一次函數。

    官方解釋:當持續觸發事件時,保證一定時間段內只調用一次事件處理函數。

    3 節流實現—時間戳和定時器

    時間戳

        var throttle = function (func, delay) {
            var prev = Date.now()
            return function () {
                var context = this;
                var args = arguments;
                var now = Date.now();
                if (now - prev >= delay) {
                    func.apply(context, args);
                    prev = Date.now();
                }
            }
        }
    
        function handle() {
            console.log(Math.random());
        }
        window.addEventListener('scroll', throttle(handle, 1000));

    定時器

        var throttle = function (func, delay) {
            var timer = null;
            return function () {
                var context = this;
                var args = arguments;
                if (!timer) {
                    timer = setTimeout(function () {
                        func.apply(context, args);
                        timer = null;
                    }, delay);
                }
            }
        }
    
        function handle() {
            console.log(Math.random());
        }
        window.addEventListener('scroll', throttle(handle, 1000))

    4 節流函數的演化過程

    ①時間戳觸發
    //在開始觸發時,會立即執行一次; 如果最后一次沒有超過 wait 值,則不觸發
    function throttle(func, wait) {
        var context, args;
        var previous = 0; // 初始的時間點,也是關鍵的時間點
    
        return function() {
            var now = +new Date();
            context = this;
            args = arguments;
            if (now - previous > wait) {
                func.apply(context, args);
                previous = now;
            }
        }
    }
    ②定時器觸發
    //首次不會立即執行,最后一次會執行,和用時間戳的寫法互補。
    function throttle(func, wait){
        var context, args, timeout;
        return function() {
            context = this;
            args = arguments;
            if(!timeout) {
                timeout = setTimeout(function(){
                    func.apply(context, args);
                    timeout = null;
                }, wait);
            }
        }
    }
    ③結合時間戳和定時器
    function throttle(func, wait) {
    
        var timer = null;
        var startTime = Date.now();  
    
        return function(){
            var curTime = Date.now();
            var remaining = wait-(curTime-startTime); 
            var context = this;
            var args = arguments;
    
            clearTimeout(timer);
    
            if(remaining<=0){ 
                func.apply(context, args);
    
                startTime = Date.now();
    
            }else{
                timer = setTimeout(fun, remaining);  // 如果小于wait 保證在差值時間后執行
            }
        }
    }

    到此,相信大家對“JavaScript節流與防抖實例分析”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    本溪市| 通州区| 陇川县| 宝山区| 南康市| 望城县| 金阳县| 双桥区| 彭泽县| 沧源| 福安市| 岳普湖县| 公安县| 巴楚县| 周宁县| 宜良县| 晋城| 安远县| 建水县| 神池县| 香格里拉县| 临颍县| 大同县| 奉化市| 新巴尔虎右旗| 平湖市| 乡宁县| 巨野县| 湘潭县| 仁怀市| 桦甸市| 阿拉善盟| 大厂| 前郭尔| 合阳县| 临海市| 三都| 合肥市| 华宁县| 平谷区| 石首市|