相信很多人都遇到过这样的问题,在做有些mouseenter,mouseout事件的时候为了展示页面动画效果加入animate(),但这种情况下,如果鼠标移动速度特别快,事件执行的速度就跟不上鼠标移动的速度,甚至有时候鼠标停下来了,事件还在缓慢的执行,这种用户体验完全不能忍受。
需要有闭包的相关知识。
做了一个类似的简单demo(可直copy在html中,注意:请引入jquery.min.js.) :
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>High Frequency Event</title>
<script type="text/javascript" src="js/jquery.min.js"></script>
<style>
.mid {
width: 250px;
margin: 20px auto;
position: relative;
}
.lis {
width: 240px;
height: 30px;
border: 1px solid #000;
color: #555;
}
.highLight {
background: #000;
height: 30px;
opacity: 0.3;
position: fixed;
top: 20px;
width: 240px;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div class="bodyContainer">
<div class = "mid">
<ul>
<li class = "lis" >this is a li</li>
<li class = "lis" >this is a li</li>
<li class = "lis" >this is a li</li>
<li class = "lis" >this is a li</li>
<li class = "lis" >this is a li</li>
<li class = "lis" >this is a li</li>
<li class = "lis" >this is a li</li>
<li class = "lis" >this is a li</li>
<li class = "lis" >this is a li</li>
</ul>
<div class="highLight" ></div>
</div>
</div>
</body>
<script type="text/javascript">
$('.lis').mouseenter(function(evt){
var _this = $(this);
$('.highLight').animate({top: _this.offset().top + 'px'},100);
_this.css('color', '#898989');
}).mouseout(function(){
$(this).css('color', '#555');
});
</script>
</html>
此时,鼠标高速在li之间移动,会发现时间执行速度完全跟不上鼠标。
可以想象,鼠标高速移动这个过程当中,每次经过一个li都会执行一个mouseenter和一个mouseout事件,这对浏览器来说是非常巨大的压力,但是,我们最终要定位的是鼠标停留的位置,那么,在鼠标起始位置和最终位置之间的一些事件是不是可以不执行。
在看下面优化过的js(用一下js替换上文demo中的javascript块即可运行):
function reduce(foo, n) {
var timeout; //调用timeout的过程用到的闭包,使得每次触发时使用的timeout是同一个,这样才能连续的记录n毫秒.
return function() {
var _this = this, arg = arguments; //此处的this是$('.li').
clearTimeout(timeout);
timeout = setTimeout(function(){foo.apply(_this, arg)}, n); //控制传进来的foo方法每n毫秒响应一次,并将此时obj $('.li')和它的arguments传入.
};
}
$('.lis').mouseenter(reduce(function(evt){ //将原本触发的方法传入reduce
var _this = $(this);
$('.highLight').animate({top: _this.offset().top + 'px'},100);
_this.css('color', '#898989');
}, 33)).mouseout(function(){ //此处数字 不宜过大也不宜过小,如果过小,时间执行频率依然会很高,如果过大,会出现“反应迟钝的现象”.
$(this).css('color', '#555');
});
如上,是控制了事件执行的频率,每33毫秒才去相应一次,在方法reduce中,用到了闭包,并用apply来传递事件执行的上下文,此方法有效的优化了高频事件的执行。