js中的计时器
在JS中做二级菜单时,被一个鼠标移出时隐藏的小问题困扰了很久.
<script> function Menu(id){ var _this=this; this.obj=document.getElementById(id); this.trigger=getFirstChild(this.obj); this.menuOne=getLastChild(this.obj); this.menuOneLi=getChildren(this.menuOne); this.menuOneLiA=[]; this.menuTwo=[]; for(var i=0;i<this.menuOneLi.length;i++){ this.menuOneLiA.push(getFirstChild(this.menuOneLi[i])); this.menuTwo.push(getLastChild(this.menuOneLi[i])); } //隐藏一级菜单 this.menuOne.style.display='none'; //隐藏二级菜单 for(var i=0;i<this.menuTwo.length;i++){ this.menuTwo[i].style.display='none'; } //为每一个一级菜单的li添加事件 for(var i=0;i<this.menuOneLiA.length;i++){ this.menuOneLiA[i].onmouseover=function(){ //清除计时器 clearTimeout(_this.timer); //隐藏所有的二级菜单 for(var j=0;j<_this.menuTwo.length;j++){ _this.menuTwo[j].style.display='none'; } //显示此li对应的二级菜单 getNextElement(this).style.display='block'; } } //一级菜单的鼠标移出事件 this.menuOne.onmouseout=function(){ _this.menuOneClear(); } this.trigger.onmouseover=function(){ _this.showMenuOne(); } } Menu.prototype.showMenuOne=function(){ clearTimeout(this.timer); this.menuOne.style.height='auto'; this.menuOne.style.display='block'; } Menu.prototype.menuOneClear=function(){ var _this=this;
//关键在于这一句,在开启一个计时器的时候,要清除掉已经开启的上一个计时器,因为计时器是会叠加的
//如果没有在清掉原有计时器的情况下,开启新的计时器,会导致菜单无论如何都会消失. clearTimeout(this.timer); this.timer=setTimeout(function(){ _this.menuOne.style.display='none'; },500); } window.onload=function(){ new Menu('header_menu'); }
HTML我就不贴了,主要是看JS的逻辑.
算了,还是贴一下吧!
<div class="header_nav_mid_handler" id="header_menu"> <a href="#" class="header_nav_mid_handler_all" id="header_btn">全部商品分类</a> <!--隐藏的一级菜单--> <ul class="header_nav_mid_menu"> <li class="header_nav_mid_menu_li bedroom"> <a href="#" class="header_nav_mid_menu_a">卧室</a> <ul class="header_nav_mid_list"> <li><a href="#">二级菜单</a></li> <li><a href="#">二级菜单</a></li> <li><a href="#">二级菜单</a></li> <li><a href="#">二级菜单</a></li> <li><a href="#">二级菜单</a></li> <li><a href="#">二级菜单</a></li> </ul> </li> </ul> </div>
在上面的JS中我是用的是自己封装的一些获取元素的方法,也贴上来共同讨论
//在IE6下,不支持getElementsByClassName()方法,此方法可以进行兼容处理 function hasClass(node,className){ var class_names=node.className.split(/\s+/); for(var i=0;i<class_names.length;i++){ if(class_names[i]==className){ return true; } } return false; } function getByClassName(className){ if(document.getElementsByClassName){ return document.getElementsByClassName(className); } var nodes=document.getElementsByTagName('*'); var arr=[]; for(var i=0;i<nodes.length;i++){ if(hasClass(nodes[i],className)){ arr.push(nodes[i]); } } return arr; } //获取第一个子元素的兼容方法 OK function getFirstChild(obj){ if(obj.firstElementChild){ return obj.firstElementChild; }else{ return obj.firstChild; } } //获取最后一个子元素的兼容方法 OK function getLastChild(obj){ if(obj.lastElementChild){ return obj.lastElementChild; }else{ return obj.lastChild; } } //获取preiousSibling的兼容方法 OK function getPrevElement(obj){ if(obj.previousElementSibling){ return obj.previousElementSibling; }else{ return obj.previousSibling; } } //获取nextSibling的兼容方法 OK function getNextElement(obj){ if(obj.nextElementSibling){ return obj.nextElementSibling; }else{ return obj.nextSibling; } } //获取子元素的方法 OK function getChildren(obj){ var nodes=obj.childNodes; var arr=[]; for(var i=0;i<nodes.length;i++){ if(nodes[i].nodeType==1){ arr.push(nodes[i]); } } return arr; } // ajax的get方法 function Ajax(url,fnSuccess,fnFailed){ var xhr=null; if(window.XMLHttpRequest){ xhr=new XMLHttpRequest(); }else{ xhr=new ActiveXObject('Microsoft.XMLHTTP'); } xhr.open('GET',url,true); xhr.send(); xhr.onreadystatechange=function(){ if(xhr.readyState==4){ if(xhr.status==200){ fnSuccess(xhr.responseText); }else{ if(fnFailed){ fnFailed(); } } } } }