javascript的防抖和節流你瞭解嗎

一:為什麼需要防抖與節流

 防抖和節流都是為瞭解決短時間內大量觸發某函數或者事件而導致的性能問題,比如在

1.用戶體驗上,觸發頻率過高導致的響應速度跟不上觸發頻率,出現延遲,假死,卡頓的現象

2.服務器上:加重服務器壓力

二:防抖

防抖是當事件或函數被觸發後,延遲n秒後在執行回調,如果在這n秒內事件或函數又被觸發,則重新計時,直到n秒內沒有觸發事件或函數,則執行回調函數

圖文解釋:

(回城的時間就相當於延遲時間,如果在回城的時間內再次觸發回城則重新倒計時回城時間)

 案例:表單輸入框事件

<!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>
    <input type="text" class="serach">
    <script>
        let serach = document.getElementsByClassName('serach')[0]
            // console.log(serach);
        serach.addEventListener('input', function() {
            console.log('向後端發起瞭請求!');
        })
    </script>
</body>
 
</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>
    <input type="text" class="serach">
    <script>
        let serach = document.getElementsByClassName('serach')[0]
            // console.log(serach);
        let timer = null; //聲明一個用於防抖的定時器變量timer
        serach.addEventListener('input', function() {
            clearTimeout(timer) //如果在定時器的時間間隔內再次觸發事件則清除定時器,重新執行新的定時器函數
                // 定時器函數
            timer = setTimeout(function() {
                console.log('向後端發起瞭請求!');
            }, 500)
 
        })
    </script>
</body>
 
</html>

運行: 

如果在500毫秒內調用多次,隻會執行最後一次

可以看出在輸入完內容後的500毫秒後才發起請求

防抖的應用場景:

1.用戶在輸入框連續輸入一串字符時,可以通過放抖策略,隻在輸入完後,才執行查詢的請 求,這樣可以有效減少請求次數,節約請求資源。(也可以用節流)

2.登錄、發短信等按鈕避免用戶點擊太快,以致於發送瞭多次請求,需要防抖

3.調整瀏覽器窗口大小時,resize 次數過於頻繁,造成計算過多,此時需要一次到位,就用到瞭防抖

4.文本編輯器實時保存,當無任何更改操作一秒後進行保存

三、節流 

控制事件發生的頻率從而達到減少一段時間內事件的觸發頻率,如控制為1s發生一次,甚至1分鐘發生一次。

圖文解釋

(當玩射擊遊戲時,無論你手點的有多快射出的彈還是有規律的發出(比如0.5發出一個彈)) 

案例:獲取鼠標的最終坐標

<!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>
    <style>
        .app {
            width: 800px;
            height: 800px;
            background-color: pink;
        }
    </style>
</head>
 
<body>
    <div class="app">
    </div>
    <script>
        let app = document.getElementsByClassName('app')[0]
        app.addEventListener('mousemove', function(e) {
            console.log(`x坐標${e.pageX},y坐標${e.pageY}`);
        })
    </script>
</body>
 
</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>
    <style>
        .app {
            width: 800px;
            height: 800px;
            background-color: pink;
        }
    </style>
</head>
 
<body>
    <div class="app">
    </div>
    <script>
        let app = document.getElementsByClassName('app')[0]
        let timer = true; //定義一個節流閥變量來控制節流閥為關閉還是開啟狀態,默認為開啟
        app.addEventListener('mousemove', function(e) {
            if (!timer) {
                return //判斷節流閥是否關閉,如果節流閥還是false(關閉狀態),則證明上次的函數未執行完,直接退出函數
            }
            timer = false; //設置節流閥為false,如果定時器函數沒有設置為true,則定時器函數沒執行,節流閥一直為關(false)
            setTimeout(function() {
                console.log(`x坐標${e.pageX},y坐標${e.pageY}`)
                timer = true //定時器函數已經執行,設置節流閥為true
            }, 500)
 
        })
    </script>
</body>
 
</html>

 運行效果:

 

使用節流後,坐標打印次數明顯變少,節流效果達成

四.防抖和節流的區別: 

防抖:如果事件被頻繁觸發,防抖能保證隻有最後一次觸發生效!前面N多次的觸發都會被忽略!

節流:如果事件被頻繁觸發,節流能夠減少事件觸發的頻率,因此,節流是有選擇性地執行一部分事件,單位時間內事件隻能觸發一次

總結

本篇文章就到這裡瞭,希望能夠給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!

推薦閱讀: