今天小馬哥讓優(yōu)化代碼,當(dāng)input 框輸入數(shù)字時(shí),會(huì)觸發(fā)一系列的運(yùn)算及邏輯處理,watch 監(jiān)控輸入變化,當(dāng)input的value 有改變時(shí),則會(huì)瘋狂請(qǐng)求處理運(yùn)算的接口,這樣一來(lái),這種處理方式則可能增加瀏覽器重繪和回流次數(shù),進(jìn)而增加了瀏覽器的負(fù)擔(dān),服務(wù)器也很疲憊,一開(kāi)始我只是很膚淺的找代碼中接口的調(diào)用次數(shù),位置,以及網(wǎng)絡(luò)請(qǐng)求多次的問(wèn)題。然而,事情并不是這么簡(jiǎn)單,所以,今天我在這里分享一下,關(guān)于節(jié)流的問(wèn)題。
1.首先我可能不會(huì)直入主題,女孩子一般喜歡拐彎抹角的說(shuō)一個(gè)問(wèn)題,我總覺(jué)得懂得拐彎肯定會(huì)多收獲不少的風(fēng)景。不羅嗦了,先講一個(gè)常見(jiàn)的通過(guò)雙向綁定來(lái)實(shí)現(xiàn)的搜索功能。
我直接貼代碼了。
<input type="text" id="search" name = "search"/>
<p id='textId'></p>
<script>
var input = document.getElementById('search');
var textId = document.getElementById('textId');
function queryData(text){
console.log(text,'text');
textId.innerHTML =text;
}
input.addEventListener('keyup',function(event){
console.log(event,'event');
queryData(this.value);
})
</script>
這段代碼瀏覽器執(zhí)行的結(jié)果是這樣的:

不要介意我的突然表白,這些都不重要,重要的是,你發(fā)現(xiàn)沒(méi)有,這就是一個(gè)典型的雙向數(shù)據(jù)綁定的原生實(shí)現(xiàn)。嘿嘿,不慌,問(wèn)題來(lái)了,你會(huì)發(fā)現(xiàn),我沒(méi)輸入一個(gè)字符的時(shí)候,都會(huì)掉一次queryData這個(gè)方法,這可能不是我特別想要的,我覺(jué)得有點(diǎn)繁瑣,我想無(wú)論我打多少個(gè)字符,在特定的時(shí)間內(nèi),只需要給我輸出一到兩個(gè)就好,否則的話在每次改變input value 值時(shí)瀏覽器可能都會(huì)發(fā)生重繪,性能肯定是不行的,為了優(yōu)化性能,我能開(kāi)始進(jìn)行第2個(gè)問(wèn)題的講解。
2.節(jié)流函數(shù)的實(shí)現(xiàn)原理。
上代碼:
// 使用節(jié)流的情況
var input = document.getElementById('search');
var textId = document.getElementById('textId');
function queryData(text){
textId.innerHTML = text;
}
input.addEventListener('keyup',function(event){
throttle(queryData,null,500,this.value);
})
function throttle(fn,context,delay,text){
clearTimeout(fn.timeoutId);
fn.timeoutId = setTimeout(function(){
fn.call(context,text);
},delay);
}
說(shuō)明:li'yong'd'n
這段代碼瀏覽器執(zhí)行的結(jié)果是這樣的:

由運(yùn)行結(jié)果可以看出,節(jié)流就是我們通過(guò)在特定的時(shí)間段內(nèi),來(lái)控制調(diào)用函數(shù)的次數(shù),進(jìn)而減少瀏覽器的重繪與回流。這只是個(gè)比較基礎(chǔ)的,原理性的實(shí)現(xiàn)函數(shù)節(jié)流的一種方案,那么如果我們像繼續(xù)優(yōu)化,請(qǐng)看第3部分的講解。
3.到一定時(shí)間間隔之后,queryData函數(shù)必然會(huì)被調(diào)用,但是又不是頻繁的調(diào)用。這既達(dá)到了節(jié)流的目的,又不會(huì)影響用戶體驗(yàn)。
上代碼:
// 使用節(jié)流的情況
var input = document.getElementById('search');
var textId = document.getElementById('textId');
function queryData(text){
textId.innerHTML = text;
console.log(text,'text');
}
input.addEventListener('keyup',function(event){
throttle(queryData,null,600,this.value);
})
function throttle(fn,context,delay,text,centerTime){
clearTimeout(fn.timeoutId);
fn.currentTime = new Date();
if(!fn.startTime){
fn.startTime = fn.currentTime;
}
if(fn.currentTime - fn.startTime > centerTime){
fn.call(context,text);
fn.startTime = fn.currentTime;
}else{
fn.timeoutId = setTimeout(function(){
fn.call(context,text);
},delay);
}
}
我來(lái)講解一下:加了一個(gè)時(shí)間間隔的比較,如果在那個(gè)時(shí)間間隔內(nèi)觸發(fā)input 框里的東西,
