LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

那些年我們忽略的高頻事件,正在拖垮你的頁(yè)面

freeflydom
2025年7月11日 10:28 本文熱度 250

在前端開發(fā)中,我們經(jīng)常需要處理一些高頻觸發(fā)的事件,比如:

  • 輸入框搜索建議(input 或 keyup
  • 窗口調(diào)整大小(resize
  • 滾動(dòng)事件(scroll
  • 鼠標(biāo)移動(dòng)(mousemove

這些事件如果每次都執(zhí)行某些代價(jià)較高的操作(如發(fā)起網(wǎng)絡(luò)請(qǐng)求、重排重繪頁(yè)面等),會(huì)對(duì)性能造成嚴(yán)重影響。為了解決這個(gè)問(wèn)題,我們可以使用 防抖(debounce) 和 節(jié)流(throttle) 技術(shù)。


?? 一、什么是防抖(Debounce)?

定義:

防抖 是指,在一段時(shí)間內(nèi)多次觸發(fā)同一個(gè)函數(shù),只有最后一次觸發(fā)后經(jīng)過(guò)指定時(shí)間沒(méi)有再次觸發(fā),才會(huì)真正執(zhí)行該函數(shù)。

類比:

就像你在打字時(shí),搜索引擎不會(huì)每次按鍵都去請(qǐng)求服務(wù)器,而是等你停下來(lái)后再請(qǐng)求。 就像你打游戲的回城,自己移動(dòng)了或被打斷了就只能重新回城,直到停下來(lái)等了指定時(shí)間才會(huì)真正回城成功。

應(yīng)用場(chǎng)景:

  • 搜索框輸入實(shí)時(shí)建議
  • 表單驗(yàn)證
  • 窗口調(diào)整尺寸
  • 多次點(diǎn)擊按鈕(避免重復(fù)提交)

? 示例代碼:

function debounce(fn, delay) {
    return function (args) {
        const that = this;
        clearTimeout(fn.id);
        fn.id = setTimeout(() => {
            fn.call(that, args); // 保留 this 上下文
        }, delay);
    };
}

?? 使用示例:

const inputA = document.getElementById('inputA');
inputA.addEventListener('keyup', debounce(function(e) {
    console.log('發(fā)送請(qǐng)求:', e.target.value);
}, 300));

?? 二、什么是節(jié)流(Throttle)?

定義:

節(jié)流 是指,在一定時(shí)間間隔內(nèi)只允許執(zhí)行一次函數(shù)。無(wú)論在這段時(shí)間內(nèi)觸發(fā)多少次,函數(shù)只會(huì)執(zhí)行一次。

類比:

就像游戲中的技能冷卻,每 5 秒只能釋放一次技能。

應(yīng)用場(chǎng)景:

  • 頁(yè)面滾動(dòng)加載更多內(nèi)容(如瀑布流)
  • 窗口調(diào)整大小(避免頻繁布局計(jì)算)
  • 實(shí)時(shí)位置更新(如地圖定位)

? 示例代碼:

function throttle(fn, delay) {
    let last = 0;
    return function (...args) {
        const now = +new Date();
        if (!last || now - last >= delay) {
            fn.apply(this, args);
            last = now;
        }
    };
}

?? 使用示例:

window.addEventListener('resize', throttle(function() {
    console.log('窗口大小變化');
}, 200));

?? 三、防抖 vs 節(jié)流:對(duì)比總結(jié)

特性防抖(Debounce)節(jié)流(Throttle)
原理在規(guī)定時(shí)間內(nèi)未被再次觸發(fā)才執(zhí)行固定時(shí)間只執(zhí)行一次
觸發(fā)頻率多次觸發(fā) → 只執(zhí)行最后一次多次觸發(fā) → 每隔一段時(shí)間執(zhí)行一次
典型用途搜索建議、表單校驗(yàn)滾動(dòng)監(jiān)聽、窗口調(diào)整、動(dòng)畫幀控制


?? 四、進(jìn)階技巧與常見問(wèn)題

1. 如何保證 this 不丟失?

在對(duì)象方法或事件回調(diào)中,this 很容易指向全局對(duì)象(如 window)。解決方案有:

? 方法一:用變量保存 this

obj.inc = debounce(function(val) {
    const that = this;
    setTimeout(function () {
        that.count += val;
    }, 500);
});

? 方法二:使用 .bind()

fn.bind(that)(args);

? 方法三:使用箭頭函數(shù)(推薦)

setTimeout(() => {
    fn(args);
}, delay);

箭頭函數(shù)不綁定自己的 this,繼承外層函數(shù)的 this,非常適用于事件處理和定時(shí)器。


2. 如何兼容箭頭函數(shù)和普通函數(shù)?

如果你傳入的是一個(gè)箭頭函數(shù)作為 fn,也要注意它的 this 綁定行為。通常我們會(huì)優(yōu)先使用箭頭函數(shù)來(lái)簡(jiǎn)化上下文管理。


3. 如何封裝成可復(fù)用的工具函數(shù)?

你可以將防抖和節(jié)流函數(shù)封裝到一個(gè)通用工具庫(kù)中,例如:

// utils.js
export function debounce(fn, delay) {
    let timer;
    return function (...args) {
        clearTimeout(timer);
        timer = setTimeout(() => {
            fn.apply(this, args);
        }, delay);
    };
}
export function throttle(fn, delay) {
    let last = 0;
    return function (...args) {
        const now = +new Date();
        if (now - last > delay) {
            fn.apply(this, args);
            last = now;
        }
    };
}

然后在組件中導(dǎo)入使用:

import { debounce } from './utils';
input.addEventListener('input', debounce(fetchSuggestions, 300));

?? 五、實(shí)際應(yīng)用案例分析

1. 輸入框搜索建議(防抖)

<input type="text" id="searchInput">
<script>
    const input = document.getElementById('searchInput');
    function fetchSuggestions(query) {
        console.log('發(fā)送請(qǐng)求:', query);
    }
    input.addEventListener('input', debounce((e) => {
        fetchSuggestions(e.target.value);
    }, 300));
</script>

2. 圖片懶加載 + 滾動(dòng)監(jiān)聽(節(jié)流)

<img data-src="image1.jpg" class="lazy-img">
<script>
    function lazyLoadImages() {
        const images = document.querySelectorAll('.lazy-img');
        images.forEach(img => {
            if (isInViewport(img)) {
                img.src = img.dataset.src;
            }
        });
    }
    window.addEventListener('scroll', throttle(lazyLoadImages, 200));
</script>

關(guān)于圖片懶加載,想詳細(xì)了解可看前端性能優(yōu)化實(shí)戰(zhàn):一文搞懂圖片懶加載(Lazy Load),從原理到代碼全解析在圖片泛濫的網(wǎng)頁(yè)時(shí)代,加載速度決定用戶體驗(yàn) - 掘金


?? 六、拓展知識(shí):高階函數(shù) & 閉包的應(yīng)用

1. 高階函數(shù)(Higher-order Function)

防抖和節(jié)流函數(shù)都是典型的高階函數(shù),它們:

  • 接收一個(gè)函數(shù)作為參數(shù)
  • 返回一個(gè)新的函數(shù)(包裝后的函數(shù))

這種設(shè)計(jì)模式廣泛應(yīng)用于現(xiàn)代 JS 開發(fā)中,尤其在 React、Vue 等框架中。

2. 閉包(Closure)

在防抖和節(jié)流函數(shù)中,我們利用了閉包來(lái)保存狀態(tài)(如 timerlastfn.id 等),這使得函數(shù)可以在多次調(diào)用之間共享狀態(tài),而不污染全局作用域。


?? 七、結(jié)語(yǔ):何時(shí)用防抖?何時(shí)用節(jié)流?

場(chǎng)景推薦技術(shù)
用戶輸入搜索建議? 防抖
窗口調(diào)整大小? 節(jié)流
滾動(dòng)加載更多內(nèi)容? 節(jié)流
頻繁點(diǎn)擊按鈕? 防抖
實(shí)時(shí)數(shù)據(jù)同步(如聊天輸入)? 防抖
動(dòng)畫幀控制? 節(jié)流

轉(zhuǎn)自https://juejin.cn/post/7525277602245574691


該文章在 2025/7/11 10:28:05 編輯過(guò)
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國(guó)內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉(cāng)儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購(gòu)管理,倉(cāng)儲(chǔ)管理,倉(cāng)庫(kù)管理,保質(zhì)期管理,貨位管理,庫(kù)位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

黄频国产免费高清视频,久久不卡精品中文字幕一区,激情五月天AV电影在线观看,欧美国产韩国日本一区二区
天堂v亚洲国产v第一次 | 欧美高清免费A√在线 | 五十六十老熟女中文字幕免费 | 亚洲精品无播放在线播放 | 午夜性色一区二区三区不卡视频 | 亚洲欧美一区另类中文字幕 |