防抖與節(jié)流放可,其實是控制事件觸發(fā)頻率的方法。
在網(wǎng)頁的實際運(yùn)行的某些場景下茫叭,有些事件會持續(xù)被觸發(fā)酬屉,比如resize不是我們需要的滾動一次,觸發(fā)一次揍愁;由于頻繁的DOM操作與資源加載呐萨,嚴(yán)重影響了網(wǎng)頁性能,甚至?xí)斐蔀g覽器崩潰莽囤。
應(yīng)用場景主要有:輸入框持續(xù)輸入垛吗,輸入內(nèi)容遠(yuǎn)程校驗,多次觸發(fā)點擊事件烁登,onScroll等怯屉。
一.防抖
抖動,即執(zhí)行饵沧。一般的抖動都是持續(xù)锨络,多次的。如果函數(shù)持續(xù)多次執(zhí)行狼牺,或許不是想要的效果羡儿。我們更希望讓它冷靜下再執(zhí)行梧兼。即當(dāng)持續(xù)觸發(fā)事件的時候裂允,函數(shù)時完全不執(zhí)行的粹胯,等到最后觸發(fā)結(jié)束后的一段時間再執(zhí)行挨措。
比如:在輸入框進(jìn)行輸入操作時,每次輸入之后都有聯(lián)想詞彈出鼎文,這個控制聯(lián)想詞的方法就需要是結(jié)束輸入后一段時間才觸發(fā)槽棍。
應(yīng)用場景:
實時搜索冀自,拖拽弹囚,登錄信息格式驗證等厨相。
此時需求:
(1)持續(xù)觸發(fā)不執(zhí)行;
(2)不觸發(fā)則隔段時間后執(zhí)行
可以很快想到利用setTimeout鸥鹉,調(diào)用要執(zhí)行的函數(shù)蛮穿,傳入arguments
首先封裝一個函數(shù),讓持續(xù)觸發(fā)的事件監(jiān)聽是封裝的這個函數(shù)毁渗,將目標(biāo)函數(shù)作為回調(diào)函數(shù)傳進(jìn)來践磅,等待一段時間過后執(zhí)行目標(biāo)函數(shù)(fun)
代碼如下:
其次,第一個需求還沒有實現(xiàn)灸异,要如何持續(xù)觸發(fā) 不執(zhí)行府适?此時持續(xù)觸發(fā)時不能有setTimeout,所以在事件持續(xù)觸發(fā)時清除定時器即可幻碱。
代碼如圖所示,當(dāng)事件持續(xù)觸發(fā)時细溅,清除定時器,setTimeout就不會執(zhí)行了儡嘶。
二.節(jié)流
節(jié)流喇聊,即讓函數(shù)有節(jié)制地執(zhí)行,而非毫無節(jié)制觸發(fā)一次執(zhí)行一次蹦狂。
而有節(jié)制地執(zhí)行誓篱,就是在一段時間內(nèi),只執(zhí)行一次凯楔。
即:一個函數(shù)只有在超過執(zhí)行周期時才執(zhí)行窜骄,周期內(nèi)調(diào)用不執(zhí)行。
應(yīng)用場景:
窗口調(diào)整摆屯,頁面滾動邻遏,搶購操作等。
在購物網(wǎng)站搶購虐骑,總會不斷點擊鼠標(biāo)准验,這時有一段時間點擊鼠標(biāo)是不起作用的,即不會產(chǎn)生效果廷没,這里就是運(yùn)用了節(jié)流糊饱,防止點擊太快產(chǎn)生bug。
分析此時的需求:
(1)持續(xù)觸發(fā)不會執(zhí)行多次
(2)到一定時間再執(zhí)行
這里劃重點:執(zhí)行的時間
所以要想控制執(zhí)行的時間颠黎,可以通過一個開關(guān)另锋,結(jié)合setTimeout。
持續(xù)觸發(fā)不執(zhí)行時狭归,開關(guān)狀態(tài)為關(guān)閉夭坪;
到一定時間,開關(guān) 打開过椎,函數(shù)執(zhí)行台舱。
代碼實現(xiàn)如下:
如果開關(guān)是關(guān)閉的,直接不執(zhí)行潭流。
或者可以通過使用時間間隔來控制竞惋,記錄上一次函數(shù)的執(zhí)行時間(prev),與當(dāng)前時間(now)作比較灰嫉,如果時間差大于特定值(wait)拆宛,就執(zhí)行。
代碼實現(xiàn)如下:
總結(jié)
二者區(qū)別:發(fā)生持續(xù)觸發(fā)事件時讼撒,防抖設(shè)置事件延遲并在空閑時間觸發(fā)事件浑厚;節(jié)流則是隔一段時間觸發(fā)一次股耽。
相同點:防抖與節(jié)流都使用了setTimeout,以此來控制函數(shù)執(zhí)行的時間钳幅。
優(yōu)點:提高性能物蝙,不會出現(xiàn)多次觸發(fā)而導(dǎo)致頁面卡頓的情況。