什么場景下使用防抖和節(jié)流
在進(jìn)行窗口的resize拔恰、scroll缝裤、輸出框內(nèi)容校驗(yàn)等操縱的時(shí)候洋闽,如果事件處理函數(shù)調(diào)用的頻率無限制溺忧,會(huì)加重瀏覽器的負(fù)擔(dān),導(dǎo)致用戶體驗(yàn)非常之差敏弃。那么為了前端性能的優(yōu)化也為了用戶更好的體驗(yàn)冰垄,就可以采用防抖(debounce)和節(jié)流(throttle)的方式來到達(dá)這種效果,減少調(diào)用的頻率权她。
為什么滾動(dòng)scroll虹茶、窗口resize等事件需要優(yōu)化
滾動(dòng)事件的應(yīng)用很頻繁:圖片懶加載、下滑自動(dòng)加載數(shù)據(jù)隅要、側(cè)邊浮動(dòng)導(dǎo)航欄等蝴罪。
在綁定scroll、resize事件時(shí)步清,但它發(fā)生的時(shí)候要门,它被觸發(fā)的頻率非常高,間隔很近廓啊。在日常開發(fā)的頁面中欢搜,事件中涉及到的大量的位置計(jì)算、DOM操作谴轮、元素重繪等等這些都無法在下一個(gè)scroll事件出發(fā)前完成的情況下炒瘟,瀏覽器會(huì)卡幀。
滾動(dòng)和頁面渲染前端性能優(yōu)化的關(guān)系
為什么滾動(dòng)需要優(yōu)化第步?前面提到了事件中涉及到大量的位置計(jì)算疮装、DOM操作、元素重繪等等粘都,這些又與頁面的渲染有關(guān)系廓推,頁面渲染又與前端的性能優(yōu)化有關(guān)系?套娃一樣翩隧,一層套著一層樊展,每一層都聯(lián)系緊密,每一層都如此平凡且重要。
回顧一下前端的渲染和優(yōu)化
web頁面展示經(jīng)歷的步驟:js—style—layout—paint—composite专缠。
網(wǎng)頁生成的時(shí)候雷酪,至少會(huì)渲染(Layout+Paint)一次。用戶訪問的過程中藤肢,還會(huì)不斷重新的重排(reflow)和重繪(repaint)太闺,用戶scroll行為和resize行為會(huì)導(dǎo)致頁面不斷的進(jìn)行重新渲染糯景,而且間隔頻繁嘁圈,容易造成瀏覽器卡幀。
防抖Debounce
防抖Debounce情景
有些場景事件觸發(fā)的頻率過高(mousemove onkeydown onkeyup onscroll)
回調(diào)函數(shù)執(zhí)行的頻率過高也會(huì)有卡頓現(xiàn)象蟀淮。 可以一段時(shí)間過后進(jìn)行觸發(fā)去除無用操作
防抖原理
一定在事件觸發(fā) n 秒后才執(zhí)行最住,如果在一個(gè)事件觸發(fā)的 n 秒內(nèi)又觸發(fā)了這個(gè)事件,以新的事件的時(shí)間為準(zhǔn)怠惶,n 秒后才執(zhí)行涨缚,等觸發(fā)事件 n 秒內(nèi)不再觸發(fā)事件才執(zhí)行。
官方解釋: 當(dāng)持續(xù)觸發(fā)事件時(shí)策治,一定時(shí)間段內(nèi)沒有再觸發(fā)事件脓魏,事件處理函數(shù)才會(huì)執(zhí)行一次,如果設(shè)定的時(shí)間到來之前通惫,又一次觸發(fā)了事件茂翔,就重新開始延時(shí)。
案例:
<template>
<div id="app">
<!-- 實(shí)現(xiàn)防抖 -->
<input type="text" v-model="searchStr">
</div>
</template>
<script>
export default {
name: 'App',
data(){
return {
searchStr:"",
fun:null
}
},
watch:{
searchStr: function (str) {
if (typeof str ==='string'){
if (str.trim().length!==0){
this.debounce(this.changeStr,1000);
}else {}
}
}
},
mounted(){
},
methods:{
// 實(shí)現(xiàn)防抖
debounce(fn,wait){
if (this.fun!==null){
clearTimeout(this.fun)
}
this.fun = setTimeout(fn,wait)
// setTimeout(() => {
// },1000)
},
changeStr(){
console.log('已觸發(fā)防抖機(jī)制')
},
}
}
</script>
<style scoped>
</style>
節(jié)流Throttle
節(jié)流Throttle情景
圖片懶加載
ajax數(shù)據(jù)請求加載
節(jié)流原理
如果持續(xù)觸發(fā)事件履腋,每隔一段時(shí)間只執(zhí)行一次函數(shù)珊燎。
官方解釋: 當(dāng)持續(xù)觸發(fā)事件時(shí),保證一定時(shí)間段內(nèi)只調(diào)用一次事件處理函數(shù)遵湖。
案例:
<template>
<div id="app">
<!-- 實(shí)現(xiàn)節(jié)流 -->
<button @click="throttle(2000)">節(jié)流</button>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return {
timeout:null
}
},
mounted(){
},
methods:{
// 實(shí)現(xiàn)節(jié)流
throttle (wait) {
if (!this.timeout) {
this.timeout = setTimeout(() => {
this.timeout = null
console.log('已觸發(fā)節(jié)流機(jī)制')
}, wait)
}
}
}
}
</script>
<style scoped>
</style>
節(jié)流防抖總結(jié)
防抖:原理是維護(hù)一個(gè)定時(shí)器悔政,將很多個(gè)相同的操作合并成一個(gè)。規(guī)定在延遲觸發(fā)函數(shù)延旧,如果在此之前觸發(fā)函數(shù)谋国,則取消之前的計(jì)時(shí)重新計(jì)時(shí),只有最后一次操作能被觸發(fā)迁沫。
節(jié)流:原理是判斷是否達(dá)到一定的時(shí)間來觸發(fā)事件烹卒。某個(gè)時(shí)間段內(nèi)只能觸發(fā)一次函數(shù)。
區(qū)別:防抖只會(huì)在最后一次事件后執(zhí)行觸發(fā)函數(shù)弯洗,節(jié)流不管事件多么的頻繁旅急,都會(huì)保證在規(guī)定時(shí)間段內(nèi)觸發(fā)事件函數(shù)。