摘要:譯通過實(shí)例講解和防抖與節(jié)流源碼中推薦的文章,為了學(xué)習(xí)英語,翻譯了一下原文鏈接作者本文來自一位倫敦前端工程師的技術(shù)投稿。首次或立即你可能發(fā)現(xiàn)防抖事件在等待觸發(fā)事件執(zhí)行,直到事件都結(jié)束后它才執(zhí)行。
[譯]通過實(shí)例講解Debouncing和Throtting(防抖與節(jié)流)
lodash源碼中推薦的文章,為了學(xué)習(xí)(英語),翻譯了一下~
原文鏈接作者:DAVID CORBACHO
本文來自一位倫敦前端工程師DAVID CORBACHO的技術(shù)投稿。我們在之前討論過這個話題(關(guān)于防抖與節(jié)流),但這次,DAVID CORBACHO通過生動的演示會將它們講的十分清晰,通俗易懂。
Debounce和throttle是兩個相似(但實(shí)現(xiàn)原理不一樣)的技術(shù)手段,用于控制一個函數(shù)在一段時間內(nèi)執(zhí)行幾次。
當(dāng)我們的函數(shù)附著在dom事件上時,使用Debounce和throttle去處理這個函數(shù)是十分有用的。為什么呢?因?yàn)槲覀冊谑录蛨?zhí)行函數(shù)之間加了一個控制層。需要注意的是,這里并不是去控制dom事件發(fā)生的頻率。
我們來看一個滑動事件的例子:
例子鏈接
當(dāng)我們使用觸控板、滾輪、或者是拉動滑動條,事件可能每秒僅僅觸發(fā)了30次左右。但如果我們滑的比較慢,他可能觸發(fā)100次。對于這些不一致的數(shù)據(jù),你在處理的時候是否考慮到了?
2011年的時候,推特網(wǎng)上出現(xiàn)了一個問題:當(dāng)你緩慢地在推特上往下滾動時,網(wǎng)站開始變得卡頓甚至沒有反應(yīng)。John Resig針對該問題發(fā)了一條博客learning-from-twitter,他覺得在scroll事件上附著復(fù)雜的函數(shù)處理是十分糟糕的。
John給出的解決方案是在scroll事件結(jié)束后,每250毫秒做循環(huán)執(zhí)行(感興趣的可以去看上面那篇博客,此時應(yīng)該是Debounce得雛形)。這種處理耦合度低,而且避免了破壞用戶體驗(yàn)。
如今處理事件的方式復(fù)雜了不少,下面向你們介紹Debounce, Throttle,對應(yīng)的也舉一些例子。
DebounceDebounce將一個組的多次調(diào)用處理為只調(diào)用一次。
想象你正在電梯里,電梯門準(zhǔn)備關(guān)閉,這時候有個人同時進(jìn)電梯,此時電梯并沒有開始上升(下降),而是電梯門再次打開。如果不斷地有人進(jìn)來,電梯將延遲他上升(或下降)的函數(shù),從而達(dá)到資源優(yōu)化的目標(biāo)。
你可以自己試試,點(diǎn)擊或者將鼠標(biāo)放在按鈕上。
例子鏈接
可以看到debounce將多次連續(xù)的事件整理成單次的事件。
Leading edge (or "immediate") [首次或立即]你可能發(fā)現(xiàn)防抖事件在等待觸發(fā)事件執(zhí)行,直到事件都結(jié)束后它才執(zhí)行。為什么不讓事件一開始就執(zhí)行,從而達(dá)到跟我們最初的設(shè)想一樣的效果呢?但是短時間內(nèi)不能連續(xù)執(zhí)行。
你可以看看這個,這是個"leading" debounce的例子。
在underscore.js中,該配置項(xiàng)叫immediate而不是leading。
你可以試試:
例子鏈接
Debounce 的實(shí)現(xiàn)我第一次看到debounce的實(shí)現(xiàn)是在John Hann(term之父)的博客中,當(dāng)時還是2009年。一年過后Jeremy Ashkenas將它加入了underscore.js。debounce最近才加入到Lodash中。
這三種實(shí)現(xiàn)方式內(nèi)部有些不同,但他們的接口十分相似。
曾經(jīng)有一段時間underscore采用了debounce中debounce/throttle 的實(shí)現(xiàn),知道2013年我在_.debounce中發(fā)現(xiàn)了一個bug,從那之后,他們分道揚(yáng)鑣。
Lodash加了很多特征在_.debounce 和 _.throttle中。原來的immediate標(biāo)識被替換成leading和trailing。你可以配置一項(xiàng),或者都配置。默認(rèn)生效的是trailing。
我在本文中不會討論新的配置項(xiàng)maxWait,雖然我不討論他,但是他很有用。事實(shí)上throttle的實(shí)現(xiàn)就是在debounce中使用了maxWait,你可以在這里看到。
Debounce 舉例 Resize 的例子當(dāng)我們在調(diào)整瀏覽器窗口時,會觸發(fā)Resize事件。
看下面的demo:
demo
可以看到,我們在resize事件中使用默認(rèn)配置trailing,因?yàn)槲覀冊谡{(diào)整窗口大小后只去最后一次的值。
鍵盤輸入自動發(fā)送ajax請求我們做的處理是當(dāng)用戶在輸入時,每50毫秒向后臺發(fā)送一次ajax請求。這時使用_.debounce能幫我們避免許多額外的消耗,我們僅僅在用戶停止輸入后發(fā)送一次請求。
這里使用leading是沒有意義的,我們需要等待用戶最后一個字符敲下。
例子鏈接
類似此場景的一個例子是進(jìn)行輸入驗(yàn)證,比如用戶在注冊時提示“密碼不足6位”。
如何使用debounce和throttle以及常見的坑許多人往往更傾向于寫自己的debounce/throttle函數(shù),或者ctrlC ctrlV別人博客里的代碼。我的建議是正確的去使用underscore 和 Lodash。如果你僅僅需要_.debounce 和 _.throttle方法,你可以使用lodash-cli生成指定函數(shù)的js,使用方法如下:(webpack等打包工具的出現(xiàn)我覺得不必考慮此問題)
npm i -g lodash-cli lodash include = debounce, throttle
簡單使用:
// WRONG $(window).on("scroll", function() { _.debounce(doSomething, 300); }); // RIGHT $(window).on("scroll", _.debounce(doSomething, 200)); // or var debounced_version = _.debounce(doSomething, 200); $(window).on("scroll", debounced_version); // If you need it debounced_version.cancel();Throttle
Throttle的作用是確保我們的函數(shù)在每一個毫秒?yún)^(qū)間只執(zhí)行一次。
Throttle和debounce主要的不同在于,監(jiān)聽的事件一直在發(fā)生,Throttle能確保我們執(zhí)行的函數(shù)在一個毫秒?yún)^(qū)間內(nèi)至少執(zhí)行一次。這里可能一時難以理解,但看了下面的例子之后,也許你就會茅塞頓開。
Throttling Examples 無限下拉一個常見的場景,用戶在下拉頁面,你需要去監(jiān)測用戶離底部多遠(yuǎn),如果接近底部時,發(fā)送一個ajax請求獲取更多內(nèi)容,然后再拼接到頁面上。
討巧的debounce在這個場景下一點(diǎn)辦法都沒有,它只會在用戶停止滑動動作后觸發(fā)。我們需要的是用戶在接近底部時發(fā)送請求,此時用戶可能正在下拉滑動條。
有了throttle我們可以經(jīng)常計(jì)算用戶離底部的距離。
例子鏈接
如有幫助,感謝點(diǎn)贊!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/99423.html
摘要:封裝方法也比較簡單,書中對此問題也進(jìn)行了處理使用定時器,讓函數(shù)延遲秒后執(zhí)行,在此秒內(nèi),然后函數(shù)再次被調(diào)用,則刪除上次的定時器,取消上次調(diào)用的隊(duì)列任務(wù),重新設(shè)置定時器。 在實(shí)際開發(fā)中,函數(shù)一定是最實(shí)用最頻繁的一部分,無論是以函數(shù)為核心的函數(shù)式編程,還是更多人選擇的面向?qū)ο笫降木幊蹋紩泻瘮?shù)的身影,所以對函數(shù)進(jìn)行深入的研究是非常有必要的。 函數(shù)節(jié)流 比較直白的說,函數(shù)節(jié)流就是強(qiáng)制規(guī)定一...
摘要:防抖防抖的作用是將多個連續(xù)的調(diào)用合并為一次調(diào)用。防抖與節(jié)流之間的重要區(qū)別是,防抖是基于上次調(diào)用來計(jì)算的而節(jié)流是基于上次調(diào)用來計(jì)算的,只要距離上次調(diào)用超過了,就可以進(jìn)行下次調(diào)用。實(shí)現(xiàn)修改自參考資料。個人認(rèn)為實(shí)現(xiàn)更好理解。 防抖(debounce) 防抖的作用是將多個連續(xù)的debounced調(diào)用合并為一次func調(diào)用。作用見參考資料1。 兩次debounced調(diào)用的間隔小于waitTim...
摘要:節(jié)流和防抖都是用來提高用戶體驗(yàn),提高網(wǎng)站性能的手段,它們的技術(shù)手段都是強(qiáng)制事件處理函數(shù)在特定的事件段內(nèi)執(zhí)行。針對上面舉例的情況,其實(shí)運(yùn)用節(jié)流和防抖都可以做到,只是它們之間又有一定的區(qū)別節(jié)流節(jié)流是在一定的時間段內(nèi),函數(shù)最多可以被調(diào)用多少次。 節(jié)流和防抖都是用來提高用戶體驗(yàn),提高網(wǎng)站性能的手段,它們的技術(shù)手段都是強(qiáng)制事件處理函數(shù)在特定的事件段內(nèi)執(zhí)行。這樣解釋可能還是不夠直觀。舉兩個例子吧:...
摘要:案例持續(xù)觸發(fā)事件時,并不立即執(zhí)行函數(shù),當(dāng)毫秒內(nèi)沒有觸發(fā)事件時,才會延時觸發(fā)一次函數(shù)。也以函數(shù)形式暴露普通插槽。這樣的場景組件用函數(shù)式組件是非常方便的。相關(guān)閱讀函數(shù)式組件自定義指令前言 有echarts使用經(jīng)驗(yàn)的同學(xué)可能遇到過這樣的場景,在window.onresize事件回調(diào)里觸發(fā)echartsBox.resize()方法來達(dá)到重繪的目的,resize事件是連續(xù)觸發(fā)的這意味著echarts...
摘要:文章來源詳談防抖和節(jié)流輕松理解函數(shù)節(jié)流和函數(shù)防抖函數(shù)防抖和節(jié)流好啦,今天的小菊花課堂之的防抖與節(jié)流的內(nèi)容就告一段落啦,感各位能耐心看到這里。 前言 陸游有一首《冬夜讀書示子聿》——古人學(xué)問無遺力,少壯工夫老始成。紙上得來終覺淺,絕知此事要躬行。,其中的意思想必大家都能明白,在學(xué)習(xí)或工作中,不斷的印證著這首詩的內(nèi)涵。所以,又有了此篇小菊花文章。 詳解 在前端開發(fā)中,我們經(jīng)常會碰到一些會持...
閱讀 2441·2021-11-23 09:51
閱讀 1867·2021-10-13 09:40
閱讀 1372·2021-09-30 10:01
閱讀 590·2021-09-26 09:46
閱讀 2233·2021-09-23 11:55
閱讀 1385·2021-09-10 10:51
閱讀 2240·2021-09-09 09:33
閱讀 2228·2019-08-29 17:25