背景
我們?cè)陂_發(fā)的過程中會(huì)經(jīng)常使用如scroll、resize盅视、touchmove等事件捐名,如果正常綁定事件處理函數(shù)的話,有可能在很短的時(shí)間內(nèi)多次連續(xù)觸發(fā)事件闹击,十分影響性能镶蹋。
因此針對(duì)這類事件要進(jìn)行節(jié)流或者防抖處理
節(jié)流
節(jié)流的意思是,在規(guī)定的時(shí)間內(nèi)只會(huì)觸發(fā)一次函數(shù)拇砰,如我們?cè)O(shè)置函數(shù)500ms
觸發(fā)一次梅忌,之后你無論你觸發(fā)了多少次函數(shù),在這個(gè)時(shí)間內(nèi)也只會(huì)有一次執(zhí)行效果
先來看一個(gè)例子
https://codepen.io/wclimb/pen/gKWLpO/
我們看到使用了節(jié)流的在1000ms
內(nèi)只觸發(fā)了一次除破,而沒有使用節(jié)流的則頻繁觸發(fā)了調(diào)用的函數(shù)
接下來看看代碼實(shí)現(xiàn)
v1 第一次不觸發(fā),不傳參實(shí)現(xiàn)
function throttle(fn,interval){
var timer;
return function(){
if(timer){
return
}
timer = setTimeout(() => {
clearTimeout(timer)
timer = null
fn()
}, interval || 1000);
}
}
效果是實(shí)現(xiàn)了琼腔,但是我在嘗試在執(zhí)行函數(shù)里console.log(this)
瑰枫,結(jié)果發(fā)現(xiàn)this
指向的是window
,而且還發(fā)現(xiàn)我們不能傳遞參數(shù)丹莲,下面就來改進(jìn)一下
v2 第一次觸發(fā)函數(shù)光坝,接收參數(shù)
function throttle(fn,interval){
var timer,
isFirst = true;
return function(){
var args = arguments,
that = this;
if(isFirst){
fn.apply(that,args)
return isFirst = false
}
if(timer){
return
}
timer = setTimeout(() => {
clearTimeout(timer)
timer = null
fn.apply(that,args)
}, interval || 1000);
}
}
防抖
防抖的意思是無論你觸發(fā)多少次函數(shù),只會(huì)觸發(fā)最后一次函數(shù)甥材。最常用的就是在表單提交的時(shí)候盯另,用戶可能會(huì)一段時(shí)間內(nèi)點(diǎn)擊很多次,這個(gè)時(shí)候可以增加防抖處理洲赵,我們只需要最后一次觸發(fā)的事件
先來看一個(gè)例子
https://codepen.io/wclimb/pen/pKPeyv/
我們看到使用了防抖的方框鸳惯,無論你在里面觸發(fā)了多少次函數(shù)商蕴,都只會(huì)觸發(fā)最后的那一次函數(shù),而沒有使用防抖的則頻繁觸發(fā)了調(diào)用的函數(shù)
v1 第一次不觸發(fā)函數(shù)
function debounce(fn,interval){
var timer;
return function(){
var args = arguments,
that = this;
if(timer){
clearTimeout(timer)
timer = null
}
timer = setTimeout(() => {
fn.apply(null,args)
}, interval || 1000);
}
}
上面這段代碼仍然可以正常執(zhí)行芝发,但是我們并沒有指定他的this
v2 第一次就觸發(fā)函數(shù)
function debounce(fn,interval){
var timer,
isFirst = true,
can = false;
return function(){
var args = arguments,
that = this;
if(timer){
clearTimeout(timer)
timer = null
}
if(isFirst){
fn.apply(that,args)
isFirst = false
setTimeout(() => {
can = true
}, interval || 1000);
}else if(can){
timer = setTimeout(() => {
fn.apply(null,args)
}, interval || 1000);
}
}
}
如有雷同绪商,純屬抄我(開玩笑)
如有錯(cuò)誤,還望指正辅鲸,僅供參考
GitHub:wclimb