这段js是不是有问题?有漏洞哎
给subNav的样式中添加一个border,你会很清楚的发现这段代码的问题。好像清除不了定时器。鼠标在展开的二级菜单上来回的上下晃,二级菜单的高度就会不听得增加。不知道有没有人发现这个问题?具体怎么解决?
给subNav的样式中添加一个border,你会很清楚的发现这段代码的问题。好像清除不了定时器。鼠标在展开的二级菜单上来回的上下晃,二级菜单的高度就会不听得增加。不知道有没有人发现这个问题?具体怎么解决?
2016-09-19
课程水平伸缩菜单制作中是这么设置的,这个练习题中CSS里面的设置和水平伸缩菜单模块的CSS样式设定不一样的,不能直接套用课程的代码,我这边运行是显示不出来二级菜单的,<ul class="subNav">大小仍为120*0,高度值为0;题目CSS中设置了.subNav{ position:absolute; top:30px; left:0; width:120px; height:0; overflow:hidden},高度为0,overflow:hidden,我也是新手一枚,说的不对还请见谅,实现要求的效果可以这样写,请参考:
<script>
window.onload=function(){
var aLi=document.getElementsByTagName('li');
for(var i=0; i<aLi.length; i++){
aLi[i].onmouseover=function(){
//鼠标经过一级菜单,二级菜单动画下拉显示出来
this.getElementsByTagName("ul")[0].style.overflow="visible";
} /*此处可以用上你的判断语句,var This=this.getElementsByTagName("ul")[0];
if(This) This.style.overflow="visible"; 个人觉得此步骤可以不用,aLi[2]、aLi[3]、aLi[4] 没有ul子节点,for循环正常循环就可以 */
//鼠标离开菜单,二级菜单动画收缩起来。
aLi[i].onmouseout=function(){
this.getElementsByTagName("ul")[0].style.overflow="hidden";
}
}
}
</script>
昨天重新认真的把代码写了一遍,试了你说的这种方法,如果if(sub.offsetHeight > 120) clearInterval(sub.timer),确实会出现你说的这些个问题,在二级菜单上面晃来晃去的,onmouseover不断触发,高度会不断增加,onmuouseover事件有冒泡行为,子节点li鼠标移动事件引发父节点ul行为,增加sub.style.height ="120px"限定高度消除子节点引起动画事件,当然动画效果会生硬,或者也可以用onmouseenter和onmouseleave,网上还有其他方法解决onmouseover冒泡行为,后面Jquery也会讲解一些;此外针对用overflow属性做法,个人理解是这样的,CSS父模块ul height=0,overflow=hidden,设置overflow=visible,虽然height=0,但是里面内容li高度不为0,利用overflow溢出显示出二级菜单,不知道这种是不是很取巧;此外也可以设置边框观察下鼠标移走时的现象,试下sub.style.height = sub.offsetHeight +/- 120+ "px"的效果,试着将border加粗加细的效果,拙见哈哈
研究好了,解决方法如下:
首先是对源代码的研究:
window.onload = function() {
var aLi = document.getElementsByClassName('li');
// alert(aLi.length);
for(var i = 0; i < aLi.length; i++) {
aLi[i].onmouseover = function() {
//鼠标经过一级菜单,二级菜单动画下拉显示出来
var sub = this.getElementsByClassName('subNav')[0];
if(sub) {//如果这个li当前是有sub的,即sub==true,执行如下代码:
// var This = sub;这里其实可以删除不用this的。
clearInterval(sub.timer);
sub.timer = setInterval(function() {
//我插入了三个alert进行调试:
//alert('+20');//弹出+20,以判断在这里执行了,几次+20.经判断,他是执行了6次,即加到了120,在120的时候,因为if判断,执行了clear
sub.style.height = sub.offsetHeight + 20 + "px";
if(sub.offsetHeight > 120) {
sub.style.height = 120+'px';
clearInterval(sub.timer)
//alert('跳出来了');//clear执行后,跳出本次循环
}
}, 30)
//alert(sub);//本来以为放在这里弹窗。会在加完120后再执行,没想到他先执行的这个,并且弹出ullistElement,即说明他找到了subNav的ul,
//最终找到原因和解决方法:
问题来了,当加载完成后,请你尝试把鼠标再放到二级菜单上移动一下,你没选择一个二级菜单,他就是把这三个alert再执行一遍,然后你就会看到ul的长度又加了20,当你不停的上下晃动鼠标,二级菜单就会不停的添加。最后加的老长。为了明显,我加了border,效果一目了然。
原因:这里,通过这个代码:alert(aLi.length);原因就明显了,因为开头的aLi,获得的是body中所有的li,包括二级菜单的。就是说你在二级菜单的每一个li上晃一下,他都会认为你是在重新执行了aLi.onmouseover这个代码,流程就再走了一遍。但是因为在高度加20那里,他高度先增加了20,然后一判断,发现高度大于120了,就赶紧跳出了。所以就会每次你晃一下,只增加了20。
解决1,从源头,只找对应的li,试过以后,我还没发现真谛。难道是要给ul一个id,然后通过id获得ul下的li集合,再判断谁有二级菜单进行显示
解决2:高度处,在判断那里,如果高度大于120了,我们就直接让高度等于120,不就得了,以后他再长,也会被这一条限制住。sub.style.height = 120+'px';
解决3:判断处,再增加前我先判断是不是大于120行不行,是的话你就停止,不是就继续。问题也就可以解决了。代码如下:
if(This.offsetHeight >= 120){
clearInterval(This.timer);
}else{
This.style.height = This.offsetHeight + 20 + "px";
}
//最后mouseout那里,就不用管了,毕竟ul的长度不会出格了,就不需要加强防备了、
}
}
举报