JavaScript 函數(shù)節(jié)流
■知識(shí)點(diǎn)
函數(shù)節(jié)流就是降低函數(shù)被調(diào)用的頻率,主要是針對DOM事件暴露出的問題,提出的一種解決方案。例如,使用 resize、mousemove、mouseover、mouseout、keydown、keyup 等事件都會(huì)頻繁地觸發(fā)事件。如果這些事件的處理函數(shù)中包含大量的耗時(shí)操作,如Ajax諧求、數(shù)據(jù)庫查詢、DOM遍歷等,如此高頻的耗時(shí)操作可能會(huì)讓瀏覽器崩潰,嚴(yán)重影響用戶體驗(yàn)。
例如,在大型網(wǎng)店平臺(tái)的導(dǎo)航欄中,為了解決mouseover和mouseout移動(dòng)過快時(shí)給瀏覽器處理帶來 的負(fù)擔(dān),特別是減輕涉及Ajax調(diào)用給服務(wù)器造成的極大負(fù)擔(dān),都會(huì)進(jìn)行函數(shù)節(jié)流處理。
■實(shí)例設(shè)計(jì)
設(shè)計(jì)思想:讓代碼在間斷的情況下重復(fù)執(zhí)行。實(shí)現(xiàn)方法:使用定時(shí)器對函數(shù)進(jìn)行節(jié)流。
【實(shí)現(xiàn)代碼】
//函數(shù)節(jié)流封裝代碼,參數(shù)method表示要執(zhí)行的函數(shù),delay表示要延遲時(shí)間,單位是毫秒
function throttle(method, delay) {
var timer=null; //定時(shí)器句柄
return function(){ //返回節(jié)流函數(shù)
var context=this, args=arguments; //上下文環(huán)境和參數(shù)對象
clearTimeout(timer); //先浩理未執(zhí)行的函數(shù)
timer=setTimeout(function() { //重新定義定時(shí)器,記錄新的定時(shí)器句柄
method.apply(context,args); //執(zhí)行預(yù)設(shè)的函數(shù)
},delay);
}
}
【應(yīng)用代碼】
設(shè)計(jì)文本框的keyup事件和窗口的resize事件,在瀏覽器中拖動(dòng)窗口,或者在文本框中輸入字符,然后在控制臺(tái)查看事件響應(yīng)次數(shù)和速度。
<input id="search" type="text" name="search">
<script>
function queryData(text){ console.log("搜索:"+ text);}
var input = document.getElementByld("search");
input.addEventListener("keyup", function(event){queryData(this.value);});
var n=0; //記錄響應(yīng)次數(shù)
function f () {console.log("響應(yīng)次數(shù):"+ ++n) ; }
window.onresize=f;
</script>
通過觀察可以發(fā)現(xiàn),在拖動(dòng)改變窗口的一瞬間,resize事件響應(yīng)了幾十次。如果在文本框中輸入字符,keyup事件會(huì)立即響應(yīng),等不及用戶輸入完一個(gè)單詞。
現(xiàn)在,使用throttleO封裝函數(shù)把上面的事件處理函數(shù)轉(zhuǎn)換為節(jié)流函數(shù),同時(shí)設(shè)置延遲時(shí)間為500毫秒。
input.addEventListener("keyup", function(event){
throttle(queryData, 500)(this.value);
});
window.onresize=throttle(f, 500);
最后再重新測試,會(huì)發(fā)現(xiàn)拖動(dòng)一次窗口改變大小,僅響應(yīng)一次,而在文本框中輸入字符時(shí),也不會(huì)立即響應(yīng),等了半秒鐘后,才顯示輸入的字符。提示,完整示例請參考本節(jié)示例源碼。
點(diǎn)擊加載更多評論>>