背景:在前端開發中,有時會為頁面綁定resize事件,或為一個頁面元素拖拽事件(其核心就是綁定mousemove)在一個正常操作中也有可能在一個短時間內觸發非常多次事件綁定程式,而DOM操作是很消耗性能的,如果為這些事件綁定一些操作DOM節點的操作的話就會引發大量的計算,在用戶看來頁面可能就一時間沒
背景:在前端開發中,有時會為頁面綁定resize事件,或為一個頁面元素拖拽事件(其核心就是綁定mousemove)在一個正常操作中也有可能在一個短時間內觸發非常多次事件綁定程式,而DOM操作是很消耗性能的,如果為這些事件綁定一些操作DOM節點的操作的話就會引發大量的計算,在用戶看來頁面可能就一時間沒有響應,這個頁面就變卡變慢了,甚至在IE下,如果綁定的resize事件進行較多DOM操作,其高頻率可能直接就使得瀏覽器崩潰。
函數節流簡單講就是讓一個函數無法在很短的時間間隔內連續調用,只有當上一次函數執行後過了你規定的時間間隔,才能進行下一次該函數的調用。
函數節流原理:用定時器,當觸發一個事件時,先setTimout讓這個事件延遲一會再執行,如果在這個時間間隔內又觸發了事件,那我們就clear掉原來的定時器,再setTimeout一個新的定時器延遲一會執行。
優缺點:
《JavaScript高級程式設計》中介紹的函數節流
function throttle(method,context){ clearTimeout(method,tId); method.tId=setTimeout(function(){ method.call(context); },100); } //調用 window.onresize=function(){ throttle(myFunc); } //法二: var throttle=function(fn,delay){ var timer=null; return function(){ var context=this,args=arguments; clearTimeout(timer); timer=setTimeout(function(){ fn.apply(context,args);//context調用fn的方法,指針指向了fn },delay); } } //調用 window.onresize=throttle(myFunc,100);
函數節流讓一個函數只有在你不斷觸發後停下來歇會才開始執行,中間你操作得太快它直接無視你。這樣做就有點太絕了,resize一般還好,但假如寫一個拖拽元素位置的程式,然後直接使用函數節流,會發現你拖動時元素是不動的,你拖完了它直接閃到終點去,所以進行優化:
var throttleV2=function(fn,delay,mustRunDelay){ var timer=null; var t_start; return function(){ var context=this,args=arguments,t_curr=+new Date(); clearTimeout(timer); if(!s_start){ t_start=t_curr; }if(t_curr-t_start>=mustRunDelay){ fn.apply(context,args); t_start=t_curr; }else{ timer=setTimeout(function(){ fn.apply(context,args); },delay); } } } window.onresize=throttleV2(myFunc,50,100);
解析:50ms的間隔內連續觸發的調用,後一個調用會把前一個調用的等待處理掉,但每隔100ms至少執行一次。
1.具有節流效果的tab切換案例:
var timer=null; function tab(obj){ var target = document.getElementById(obj); var spans = target.getElementsByTagName("span"); var lis = target.getElementsByTagName("li"); for(var i=0;i<spans.length;i++) { spans[i].onmouseover = function(num){ return function(){ clearTimeout(timer); timer=setTimeout(function(){ for(var j=0; j<spans.length;j++) { spans[j].className = ""; lis[j].className = ""; } spans[num].className = "current"; lis[num].className = "show"; },300); } }(i); spans[i].onmouseout=function(){ clearTimeout(timer); } } } tab("one");
2.屏幕縮放節流案例:
<body> <div id="demo"></div> </body> </html> <script> var demo=document.getElementById("demo"); var num=0; window.onresize=throll(function(){ demo.innerHTML=window.innerWidth || document.documentElement.clientWidth; num++; alert(num); },300); function throll(fn,delay){ var timer=null; return function(){ clearTimeout(timer); timer=setTimeout(fn,delay); } } </script>