防抖和節流

這是我參與8月更文挑戰的第8天,活動詳情查看:8月更文挑戰html

前置知識

setTimeout函數ajax

setTimeout() 方法用於在指定的毫秒數後調用函數或計算表達式。瀏覽器

提示:  1000 毫秒= 1 秒。 、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、 setTimeout.pngmarkdown

clearTimeout函數 clearTimeout() 方法可取消由 setTimeout() 方法設置的 timeout。 clearTimeout() 方法的參數必須是由 setTimeout() 返回的 ID 值。app

語法

image-20210808134440985

clearTimeout.png setInterval函數異步

超時值是指在指定時間以後執行代碼,間歇時間值是指每隔指定的時間就執行一次代碼。設置超時調用的方法是setTimeout(),設置間歇調用的方法是setInterval()。函數

setInterval() 方法會不停地調用函數,直到 clearInterval() 被調用或窗口被關閉。由 setInterval() 返回的 ID 值可用做 clearInterval() 方法的參數。post

函數防抖

概念: 在事件被觸發n秒後再執行回調,若是在這n秒又被觸發,則從新計時ui

舉例:點擊觸發事件函數this

請輸入數字:<input id="normal"></input>
​
<script>
function ajax(value) {
            console.log('ajax 請求:', value);
}
let emitBussiness = document.getElementById('normal')
emitBussiness.addEventListener('keyup', function (e) {
    ajax(e.target.value)
})
</script>
複製代碼

沒有防抖.png 這個函數的做用是每按下一個按鍵,就輸出當前輸入框裏的值。

假設咱們想輸入一串字符,而後發送請求查詢這串字符,但這串字符還沒輸完就發送了不少個請求,有些不符合實際狀況。

接下來,咱們在這個函數中加入防抖。

請輸入數字:<input id="normal"></input>
    
    <script>
        function ajax(value) {
            console.log('ajax 請求:', value);
        }
        function delayAjax(fun, delay) {
            return function (val) {
                let that = this
                let args = val
                //console.log('before', fun.setId);
                clearTimeout(fun.setId)
                fun.setId = setTimeout(() => {
                                fun.call(that, val)
                            }, delay)
                //console.log('after', fun.setId);
            }
        }
        let emitBussiness = document.getElementById('normal')
        let funD = delayAjax(ajax, 1000)
        emitBussiness.addEventListener('keyup', function (e) {
            funD(e.target.value)
        })
    </script>
複製代碼

注意:clearTimeout(fun.setId) 這條語句的位置要在下面的setTimeout函數以前。這時由於第一次按鍵,fun.setId保存的值是undefined,第二次按鍵,fun.setId保存的值是1,第三次按鍵,fun.setId保存的值是2,... 也就是說,在執行setTime函數以前,fun.SetId保存的是上一次setTimeout的返回值。而咱們的需求也正是當距離上一次按鍵的時間間隔不到指定事件就取消上一次的請求。

防抖.png 首先,按下按鍵1,1秒以內沒有按下別的按鍵,輸出'ajax 請求:1';按下按鍵2,1秒以內沒有按下別的按鍵,輸出'ajax 請求:12';接着,快速按下三、四、五、6,間隔時間小於1秒,接着等待1秒後,輸出'ajax 請求:123456';可見咱們的防抖起了做用。

咱們加入了防抖之後,當你在頻繁的輸入時,並不會發送請求,只有當你在指定間隔內沒有輸入時,纔會執行函數。若是中止輸入可是在指定間隔內又輸入,會從新觸發計時。

函數節流

概念: 規定在一個單位時間內,只能觸發一次函數。若是這個單位時間內觸發屢次函數,只有一次生效。

指當連續觸發事件時,在 n 秒中只執行一次函數。

好比,咱們一直喝水,但不是一喝水就上廁所,而是每隔一段時間就去上廁所。

初始html代碼:(沒有節流)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="content"
        style="height:150px;line-height:150px;text-align:center; color: #fff;background-color:#ccc;font-size:80px;width:100%">
    </div>
    <script>
        let num = 0;
        const content = document.getElementById('content');
        function count() {
            // 一些異步請求或者別的代碼
            content.innerHTML = num++;
        };
        content.onmousemove = count;
    </script> 
</body>
</html>
複製代碼

實現1--時間戳:

<div id="content"
        style="height:150px;line-height:150px;text-align:center; color: #fff;background-color:#ccc;font-size:80px;width:100%">
    </div>
    <script>
        // 第一次觸發,最後一次不觸發
        // 顧頭不顧尾
        
        // 當觸發事件時,執行函數時取出當前時間戳,用當前時間戳減去一開始設置的時間戳,若是時間差值>設置的時間週期,就執行函數並更新當前時間爲時間戳。
        function throttle(func, wait) {
            let context, args;
            //以前的時間戳
            let old = 0;
            return function() {
                // 若是不對this作處理,func裏面的this指向window,但咱們要讓this指向當前的div對象
                context = this
                args = arguments
                // 獲取當前時間戳
                let now =  new Date().valueOf();
                if ( now - old > wait ) {
                    // 當即執行
                    func.apply(content, args)
                    old = now
                }
            }
        }

        let num = 0;
        const content = document.getElementById('content');
        function count() {
            // 一些異步請求或者別的代碼
            content.innerHTML = num++;
        };
        content.onmousemove = throttle(count, 2000);
    </script> 
複製代碼

實現2--定時器:

<div id="content"
        style="height:150px;line-height:150px;text-align:center; color: #fff;background-color:#ccc;font-size:80px;width:100%">
    </div>
    <script>
        // 顧尾不顧頭 
        // 第一次不會觸發,最後一次會觸發

        // 觸發事件時,咱們會設置一個定時器timeout,再觸發這個事件時,若是timeout存在,就不執行;直至執行後定時器設置爲null。
        function throttle(func, wait) {
            let context, args, timeout;
            

            return function() {
                context = this
                args = arguments
                if(!timeout) {
                    timeout = setTimeout(() => {
                        timeout = null
                        func.apply(context, args)
                    }, wait)
                }
        
            }
        }

        let num = 0;
        const content = document.getElementById('content');
        function count() {
            // 一些異步請求或者別的代碼
            content.innerHTML = num++;
        };
        content.onmousemove = count;
    </script> 
複製代碼

總結

  • 函數防抖和函數節流都是防止某一時間頻繁觸發,可是原理卻不同。
  • 函數防抖是某一段時間內只執行一次,而函數節流是間隔時間執行。

應用場景

防抖

  • search搜索聯想,用戶在不斷輸入值時,用防抖來節約請求資源。
  • 不斷的調整瀏覽器窗口大小會不斷的觸發resize事件,用防抖來讓其只觸發一次。

節流

  • 鼠標不斷點擊觸發,mousedown(單位時間內只觸發一次)
  • 監聽滾動事件,好比是否滑到底部自動加載更多,用throttle來判斷

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

參考

連接:juejin.cn/post/684490…

連接:juejin.cn/post/684490…

相關文章
相關標籤/搜索