背景
????今天在coding的時(shí)候,做了一個(gè)搜索框,也正是這個(gè)搜索框,讓我和后臺(tái)小伙伴直接由鐵磁變?yōu)樗芰闲值堋D堑降装l(fā)生啥了呢?其實(shí)很簡(jiǎn)單,其實(shí)很無(wú)奈,就是我用王者的手速把他的接口訪問(wèn)崩了!
????我們?cè)谄綍r(shí)開(kāi)發(fā)的時(shí)候,會(huì)有很多場(chǎng)景會(huì)頻繁觸發(fā)事件,比如說(shuō)搜索框?qū)崟r(shí)發(fā)請(qǐng)求,onmousemove,resize,onscroll等等,有些時(shí)候,我們并不能或者不想頻繁觸發(fā)事件,咋辦呢?這時(shí)候就應(yīng)該用到函數(shù)防抖和函數(shù)節(jié)流了!
函數(shù)防抖(debounce)
????什么是防抖?短時(shí)間內(nèi)多次觸發(fā)同一個(gè)事件,只執(zhí)行最后一次,或者只在開(kāi)始時(shí)執(zhí)行,中間不執(zhí)行。舉個(gè)栗子:你去乘坐公交車(chē),不停地上人,連續(xù)上人的過(guò)程中司機(jī)師傅是不會(huì)開(kāi)車(chē)的,只有當(dāng)最后一個(gè)人上車(chē)了,老司機(jī)才會(huì)開(kāi)車(chē)!嘿嘿嘿!我們以不停地觸發(fā)onmousemove事件,讓數(shù)字 1為例。代碼如下:
- 不使用防抖和節(jié)流,數(shù)字會(huì)像得了羊癲瘋一樣不停地增長(zhǎng)
//變量初始化
var xcd = document.getElementById(
'xcd'),count = 1;
//要執(zhí)行的操作 數(shù)字 1
function doSomething() {xcd.innerHTML = count ;
};
//觸發(fā)onmousemove事件 正常情況下
xcd.onmousemove =
doSomething;
//綠色基礎(chǔ)版:
function debounce(
doSomething,
wait){var timeout;//需要一個(gè)外部變量,為增強(qiáng)封裝,所以使用閉包
return function(){var _this = this,_arguments = arguments;//arguments中存著eclearTimeout(timeout);timeout =
setTimeout(
function(){
doSomething.apply(_this,_arguments); },
wait);}
}
//觸發(fā)onmousemove事件
xcd.onmousemove = debounce(
doSomething,1000);
????這個(gè)綠色基礎(chǔ)版雖然簡(jiǎn)單,但是已經(jīng)能夠解決大部分需求場(chǎng)景了,沒(méi)有啥特殊需求使用這個(gè)版本就行了!用起來(lái)簡(jiǎn)直像吃了巴豆一樣,duangduangduang,極其通暢!But,還會(huì)有一些其他需求,比如我想立即執(zhí)行,就是連續(xù)觸發(fā)事件的開(kāi)始時(shí)立即執(zhí)行一次,后連續(xù)觸發(fā)不執(zhí)行,我們用isImmediate表示是否立即執(zhí)行,代碼如下:
//立即執(zhí)行版
function debounce(
doSomething,
wait,isImmediate){var timeout;
return function(){var _this = this,_arguments = arguments;clearTimeout(timeout);
if(isImmediate){var isTrigger = !timeout;timeout =
setTimeout(
function(){timeout = null;},
wait)isTrigger&&
doSomething.apply(_this,_arguments);}
else{timeout =
setTimeout(
function(){
doSomething.apply(_this,_arguments); },
wait);}}
}
//觸發(fā)onmousemove事件
xcd.onmousemove = debounce(
doSomething,1000,
true);
函數(shù)節(jié)流(throttle)
????什么是節(jié)流?節(jié)流是連續(xù)觸發(fā)事件的過(guò)程中以一定時(shí)間間隔執(zhí)行函數(shù)。節(jié)流會(huì)稀釋你的執(zhí)行頻率,比如每間隔1秒鐘,只會(huì)執(zhí)行一次函數(shù),無(wú)論這1秒鐘內(nèi)觸發(fā)了多少次事件。
????舉個(gè)栗子:你每天要喝好多水,但是你不會(huì)每喝完一口水都要去一次廁所,如果有盆友是醬紫的話,我勸你還是去醫(yī)院看看吧→_→廁所看你都煩~你雖然一直在喝水,但是不會(huì)一直去廁所,通常的節(jié)奏是!喝水喝水喝水上廁所!喝水喝水喝水上廁所!雖然一直在觸發(fā),但是每隔一段時(shí)間只會(huì)執(zhí)行一次操作,這就是函數(shù)節(jié)流!
//綠色基礎(chǔ)版之時(shí)間戳版
function throttle(
doSomething,
wait){var _this,_arguments,initTime = 0;
return function(){var now = new Date();//將new date()轉(zhuǎn)化為時(shí)間戳_this = this;_arguments = arguments;
if(now - initTime>
wait){
doSomething.apply(_this,_arguments);initTime = now;}}
}
//觸發(fā)onmousemove事件
xcd.onmousemove = throttle(
doSomething,1000);
//綠色基礎(chǔ)版之定時(shí)器版
function throttle(
doSomething,
wait){var timeout;
return function(){var _this = this;_arguments = arguments;
if(!timeout){timeout =
setTimeout(
function(){timeout = null;
doSomething.apply(_this,_arguments);},
wait);};}
}
//觸發(fā)onmousemove事件
xcd.onmousemove = throttle(
doSomething,1000);
????同樣,以上兩個(gè)節(jié)流的綠色基礎(chǔ)版也可以滿足大多數(shù)需求場(chǎng)景啦!這兩個(gè)版本有什么區(qū)別呢?時(shí)間戳版會(huì)在開(kāi)始時(shí)立即執(zhí)行一次,最后時(shí)間間隔內(nèi)不再執(zhí)行;定時(shí)器版開(kāi)始時(shí)不執(zhí)行,最后時(shí)間間隔內(nèi)再執(zhí)行一次。可以根據(jù)自己的實(shí)際需求選擇合適的版本。
????當(dāng)然,可能還有一些BT的產(chǎn)品會(huì)問(wèn)你,能不能先立即執(zhí)行一次,中間固定間隔時(shí)間執(zhí)行,最后在執(zhí)行一次呢?這就到了裝B的時(shí)候了。像我這么牛X的前端,必須的啊,把兩種合在一起就行了,雙修什么的最喜歡了*@ο@*
//節(jié)流之雙劍合璧版
function throttle(
doSomething,
wait) {var timeout, _this, _arguments,previous = 0;var later =
function() {previous = new Date();timeout = null;
doSomething.apply(_this, _arguments)};var throttled =
function() {var now = new Date();//下次觸發(fā)
doSomething 剩余的時(shí)間var remaining =
wait - (now - previous),_this = this;_arguments = arguments;// 如果沒(méi)有剩余的時(shí)間了
if (remaining <= 0) {
if (timeout) {clearTimeout(timeout);timeout = null;}previous = now;
doSomething.apply(_this, _arguments);}
else if (!timeout) {timeout =
setTimeout(later, remaining);}};
return throttled;
}
//觸發(fā)onmousemove事件
xcd.onmousemove = throttle(
doSomething,1000);
深入理解函數(shù)防抖和節(jié)流,合理選擇防抖或節(jié)流,能解決很多帕金森疾病,實(shí)乃出門(mén)旅行,居家生活之必備良品!OK就醬,我就是我,我瞅自己都上火!不定期分享一些前端知識(shí)點(diǎn)和面試點(diǎn),喜歡點(diǎn)波關(guān)注唄!
參考:https://github.com/mqyqingfeng/Blog
總結(jié)
以上是生活随笔為你收集整理的虾扯蛋之函数防抖和节流的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。