今天在imooc上看的伸缩菜单的js实现 http://www.imooc.com/video/93
自己实践的时候发现这个代码是有问题的。 先上错误代码
<ul>
<li style="background-color: red; width: 100px">第一个</li>
<li style="background-color: red; width: 100px">第二个</li>
<li style="background-color: red; width: 100px">第三个</li>
</ul>
<script type="text/javascript">
window.onload = function () {
var ls = document.getElementsByTagName("li");
for (var i = 0; i < ls.length; i++) {
ls[i].onmouseover = function () {
var This = this;
This.time = setInterval(function () {
This.style.width = This.offsetWidth + 20 + "px";
if(This.offsetWidth >= 160){
This.style.width = 160 + "px";
clearInterval(This.time);
}
}, 30)
};}
for (var i = 0; i < ls.length; i++) {
ls[i].onmouseout = function () {
var This = this;
This.time= setInterval(function () {
This.style.width = This.offsetWidth - 20 + "px";
if(This.offsetWidth <=100) {
This.style.width = 100 + "px";
clearInterval(This.time);
}
}, 30)
};
}
}
</script>
这个代码忽略了两个问题。
1.如果鼠标悬浮瞬间离开,到空白处(即长度未增加多少的时候),多来几次,即可能造成无限循环
原因:离开时,悬浮变长的动作还没完,悬浮时,离开减小的动作还没完,发生冲突,某个时刻满足循环条件会出现动画循环
2.如果鼠标悬浮瞬间离开,到另一个list处,多试几次,会发生什么? 我们也是可以看到无限循环动画的发生。
原因 把增减动画都归类到了 obj.time属性里面。如果按2到操作,极有可能出现在某一时刻同一obj增减到冲突,本来应该减的,但是增的动作还没完,就会一直增,导致减也也完成不了
解决办法 :1------》在鼠标悬浮函数开头清空鼠标离开的所有动画,在鼠标离开函数开头清空鼠标悬浮的所有动画
2--------》 鼠标悬浮和离开这两个动画应该分开,不能用同一个属性,要分别用两个属性表示(最后面讲一讲为什么要用属性,不能用全局变量,不能用局部变量,同时也讲一下为什要用v a r T his= this)
正确代码如下:
<script type="text/javascript">
window.onload = function () {
var ls = document.getElementsByTagName("li");
for (var i = 0; i < ls.length; i++) {
ls[i].onmouseover = function () { //内部函数1
var This = this;
clearInterval(This.off);
This.on = setInterval(function () {
This.style.width = This.offsetWidth + 20 + "px";
if(This.offsetWidth >= 160){
This.style.width = 160 + "px";
clearInterval(This.on);
}
}, 30)
};}
for (var i = 0; i < ls.length; i++) {
ls[i].onmouseout = function () { //内部函数2
var This = this;
clearInterval(This.on)
This.off = setInterval(function () {
This.style.width = This.offsetWidth - 20 + "px";
if(This.offsetWidth <=100) {
This.style.width = 100 + "px";
clearInterval(This.off);
}
}, 30)
};
}
}
</script>
为什么用属性?
首先我们肯定不能用局部变量,在内部函数2(1)肯定无法访问内部函数1(2)的局部变量,那么就没办法清除“动画栈”里的动画了
为什么不用全局变量 o n 、o f f. 我们考虑一种情况。假设我从listA快速移到listB。 此时on表示增加的动画 off表示减小的动画
离开A到B的一瞬间 B触发onmouseover 执行clearInterval(off) A还没来得及减小到原来的长度就被迫停止了
换句话说 如果用全局变量从此动画不在区分是针对哪个对象的动画
为什么用var This = this ?
set interval是延时函数。执行的时候this已经变成了window 而我们想要this绑定到list上 所有用变量This储存lIst 的地址,因为执行var This = this.this绑定的对象还没有变化