您的位置:首页 > Web前端 > JavaScript

关于伸缩菜单js代码正确实现

2017-03-29 12:13 477 查看
今天在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绑定的对象还没有变化


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: