[TOC] #### 1. 節(jié)流介紹 --- 節(jié)流: n 秒內(nèi)只運行一次,若在 n 秒內(nèi)重復觸發(fā),只有第一次生效 節(jié)流的應用場景: 1\. 滾動加載: 監(jiān)聽頁面滾動到底部的時候觸發(fā) 2\. 拖拽場景: 固定時間只執(zhí)行一次,防止高頻率的位置變動 #### 2. 滾動加載-節(jié)流處理 --- 首先編寫監(jiān)聽頁面滾動距離的方法,當向下滑動時,可以看到控制臺執(zhí)行了很多次的輸出,如果我們要根據(jù)頁面滑動距離來計算代碼邏輯,這樣頻繁的執(zhí)行計算會非常損耗系統(tǒng)性能,我們可以使用節(jié)流來優(yōu)化這個問題 ``` <style> body { height: 2000px; background: lightsalmon; } </style> <script> let count = 1 function scrollFn() { console.log('監(jiān)聽頁面滾動次數(shù): ', count++); } document.onscroll = scrollFn </script> ``` 節(jié)流的實現(xiàn)思路: 1\. 借助 setTimeout 定時器,控制事件回調(diào)是否執(zhí)行 2\. 獲取每次事件執(zhí)行的時間與上一次執(zhí)行的時間差 3\. 判斷時間差是否已超過設定的時間間隔,超過時立即執(zhí)行函數(shù),沒有超過時取消后續(xù)的定時器任務 4\. 最后一次事件的觸發(fā),會執(zhí)行完成 使用節(jié)流函數(shù)優(yōu)化后的代碼: ```javascript // 節(jié)流函數(shù) function throttle(fn, time) { // 上一次的執(zhí)行時間 let pre = 0 let timeout = null return function (...args) { const now = Date.now() // 時間差超過了設定的時間間隔 if (now - pre > time) { pre = now fn.apply(this, args) } else { // 沒有超過設定的時間間隔,則后續(xù)的事件會直接清除 if (timeout) { clearTimeout(timeout) timeout = null } // 最后一次的事件會觸發(fā) timeout = setTimeout(() => { pre = now fn.apply(this, args) }, time); } } } document.onscroll = throttle(scrollFn, 300) ```