一、為啥要防抖或節(jié)流板乙?
為了優(yōu)化高頻率事件是偷,比如onscroll滾動、oninput搜索框募逞、resize窗口大小變化蛋铆、onkeydown、onkeyup等等凡辱,這些高頻率事件很有可能造成頁面卡頓戒职,影響用戶體驗。為啥高頻事件就會導(dǎo)致頁面卡頓呢透乾?這些又跟頁面的渲染有關(guān)系洪燥。
-
前端的渲染過程
web頁面的展示過程:
Javascript -> Style -> Layout -> Paint -> Composite
一般我們會使用Javascript來實現(xiàn)一些視覺變化的效果,比如做一個動畫或添加一些dom元素乳乌;
Style階段確定每個DOM應(yīng)該用什么css樣式規(guī)則捧韵;
Layout,布局汉操,這一步具體計算每個dom元素最終在屏幕上顯示的大小和位置再来;
Paint,繪制階段磷瘤,進(jìn)行dom的繪制(包括繪制文字芒篷、顏色、圖像采缚、邊框和陰影等dom元素所有的可視效果)针炉。一般來說,這個繪制過程是在多個層上完成的扳抽。
-
Composite:渲染層合并篡帕,在每個層上完成繪制過程之后殖侵,瀏覽器會將所有層按照合理的順序合并成一個圖層,然后顯示在屏幕上镰烧。(所以做一些動畫效果盡量使用css3的transform等屬性拢军,因為該屬性是脫離文檔流,不用合并渲染層的)怔鳖。
樣式變化是重繪茉唉,布局和位置變化是重排。重排一定導(dǎo)致重繪败砂,重繪不一定導(dǎo)致重排赌渣。
網(wǎng)頁生成的時候,至少會渲染(Layout+Paint)一次昌犹,用戶訪問過程中,還會不斷的重排(reflow)和重繪(repaint)览芳,用戶scroll行為resize行為會導(dǎo)致頁面不斷的進(jìn)行重新渲染斜姥,而且間隔頻繁,容易造成瀏覽器卡幀沧竟。運用防抖和節(jié)流可以有效降低代碼的執(zhí)行效率铸敏,從而解決高頻率事件的頁面卡頓問題。
節(jié)流
什么是節(jié)流:是保證一段時間內(nèi)悟泵,代碼只執(zhí)行一次杈笔。比如設(shè)置每一秒執(zhí)行一次。
-
節(jié)流實現(xiàn):
var throttle = function(func,delay){ var timer = null return function(){ var context = this var args = arguments if(!timer){ timer = setTimeout(() => { func.apply(context,args) timer = null }, delay); } } } function handle(){ } window.addEventListener('scroll',throttle(handle,1000))
防抖
-
什么是防抖:是在一段時間結(jié)束之后糕非,才觸發(fā)一次事件蒙具。如果一段時間內(nèi)未結(jié)束再次觸發(fā)了事件,那么就會重新計算這段時間朽肥。
-
防抖實現(xiàn):
function debounce(func,wait){ var timeout return function(){ clearTimeout(timeout) timeout = setTimeout(func,wait) } } function handle(){ } window.addEventListener('scroll',debounce(handle,1000))
-
使用場景:
- 防抖:實時搜索(keyup)禁筏,拖拽(mousemove)。
- 節(jié)流:窗口調(diào)整(resize)衡招,頁面滾動(scroll)篱昔,搶購和瘋狂點擊(mousedown)
總結(jié):
節(jié)流:在規(guī)定的間隔時間范圍內(nèi)不會重復(fù)觸發(fā)回調(diào),只有大于這個時間間隔才會觸發(fā)回調(diào)始腾,把頻繁觸發(fā)變?yōu)樯倭坑|發(fā)州刽。
防抖:前面的所有的觸發(fā)多被取消,最后一次執(zhí)行在規(guī)定的時間之后才會觸發(fā)浪箭,也就是說如果連續(xù)快速的觸發(fā)穗椅,只會執(zhí)行一次。