`

Web中连续触发事件影响性能的解决办法

阅读更多

        当类似用户改变浏览器窗口大小的事件,有可能会连续触发多次。有的页面需要做到联动处理,在多次触发中可能会卡死,尤其是在性能低下的IE上若每次触发都执行一些图形渲染更是个大问题。

 

        以下代码就解决了这个问题。绑定了window的resize事件,但是每次触发后会延迟500毫秒,给每次触发这个事件进行了tag标识,只处理连续触发后的最后一次的触发行为。

 

$(function(){
			var tag = 0;
			var coverChartWidth  = function(t){
				if(t != tag){return;}
				var w = $(document).width() || 0;
				if(w < 1150){
					$('#chartTable').width(1150);
				}
			};
			$(window).bind('resize',function(){
				tag++;
				(function(t){
					setTimeout(function(){
						coverChartWidth(t);
					},500);
				})(tag);
			});
		});
		

 

用tag标识的方法确实太麻烦了,借鉴网友的更好的方法代码如下:

//可进一步扩展为支持可传参的fn
var onFooEndFunc = function(fn) {
    var delay = 50; // 根据实际情况可调整延时时间
    var executionTimer;
    return function() {
        if (!!executionTimer) {
            clearTimeout(executionTimer);
        }
        //这里延时执行你的函数
        executionTimer = setTimeout(function() {
            //alert('123');
            fn();
        }, delay);
    };
};

在使用的时候直接调用这个 onFooEndFunc 函数,把你需要的处理函数传进去即可。 

下面以document.onmousemove为例,自己试试运行的效果,使用延时处理前,移动鼠标,会发现事件触发非常频繁,使用延时处理后,移动鼠标,事件就没那么频繁了。

测试代码:(在线测试:http://pgkk.github.io/testDelayEvent.html

<html>
<head>
<script type="text/javascript">
var count = 0;
         var myfn = function() {
             document.getElementById("TextArea1").value = "Executed " + (++count) + " times.";
         }
         var normalevent = function() {
             count = 0;
             document.getElementById("TextArea1").value = "Executed 0 times.";
             document.onmousemove = myfn;
         };
         var endevent = function() {
             count = 0;
             document.getElementById("TextArea1").value = "Executed 0 times.";
             document.onmousemove = onFooEndFunc(myfn);
         };
</script>
</head>
<body>
<input id="normal" value="恢复正常" onclick="normalevent()" type="button" />&nbsp;
<input id="end" value="使用延时" onclick="endevent();" type="button" />&nbsp;

<textarea id="TextArea1" style="height: 40px; width: 200px; color: #ff0000; clip: rect(auto, auto, auto, auto);"></textarea>
</body>
</html>

 

上面只是以 document.onmousemove为例,还有很多其他DOM事件存在相同问题,例如onScroll, onMouseMove, onResize,同理,都可以用这个方法来解决,具体还可以看这里的例子,方法本质上都是一样的。

1
0
分享到:
评论
2 楼 mfkvfn 2014-03-05  
mfkvfn 写道
直接用clearTimeout不就行了。
    $(function(){   
                $(window).bind('resize',function(){  
                    window.xxxTimer && clearTimeout(window.xxxTimer);  
                    window.xxxTimer= setTimeout(function(){  
                            coverChartWidth(t);  
                        },500);  
                    };  
                });  
      });  



写错了。应该是
$(function(){   
                $(window).bind('resize',function(){  
                    window.xxxTimer && clearTimeout(window.xxxTimer);  
                    window.xxxTimer= setTimeout(function(){  
                            //window的resize监听处理;  
                     },500);   
                });  
});  


1 楼 mfkvfn 2014-03-05  
直接用clearTimeout不就行了。
    $(function(){   
                $(window).bind('resize',function(){  
                    window.xxxTimer && clearTimeout(window.xxxTimer);  
                    window.xxxTimer= setTimeout(function(){  
                            coverChartWidth(t);  
                        },500);  
                    };  
                });  
      });  

相关推荐

Global site tag (gtag.js) - Google Analytics