在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();
}
}
}
}
}

js中的计时器的更多相关文章

  1. JS中的计时器事件

    JS可以实现很多java代码不易完成的功能.这里学习一些js中的计时器事件. JavaScript 一个设定的时间间隔之后来执行代码,称之为计时事件. 主要通过两个方法来实现: 1.setInterv ...

  2. js中的计时器事件`setTimeout()` 和 `setInterval()`

    js中的计时器事件 在js中,通常会有一些事件,我们需要让它 间隔一段时间之后再发生,或者 每隔一段时间 发生一次,那就需要用到我们js中的计时事件 计时事件主要有两种: setTimeout() - ...

  3. 【转】JS中setTimeout和setInterval的最大延时值详解

    前言 JavaScript提供定时执行代码的功能,叫做定时器(timer),主要由setTimeout()和setInterval()这两个函数来完成.而这篇文中主要给大家介绍的是关于JS中setTi ...

  4. JS中的函数节流throttle详解和优化

    JS中的函数节流throttle详解和优化在前端开发中,有时会为页面绑定resize事件,或者为一个页面元素绑定拖拽事件(mousemove),这种事件有一个特点,在一个正常的操作中,有可能在一个短的 ...

  5. Node.js中Process.nextTick()和setImmediate()的区别

    一.Webstrom使用node.js IDE的问题 在区别这两个函数之前来说一下Webstrom使用node.js IDE的问题,在配置Node.js的IDE了,但setImmediate().re ...

  6. Node.js中setTimeout和setInterval的使用

    Node.js和js一样也有计时器,超时计时器.间隔计时器.及时计时器,它们以及process.nextTick(callback)函数来实现事件调度.今天先学下setTimeout和setInter ...

  7. 为什么JS是单线程?JS中的Event Loop(事件循环)?JS如何实现异步?setimeout?

    https://segmentfault.com/a/1190000012806637 https://www.jianshu.com/p/93d756db8c81 首先,请牢记2点: (1) JS是 ...

  8. js中的this介绍

    今天跟大家一起简单的来了解一下js中一个有趣的东西,this. 在js中我们用面向对象的思想去编写的时候,各个模块之间的变量就不那么容易获取的到了,当然也可以通过闭包的方式拿到其他函数的变量,如果说每 ...

  9. javascript基础入门之js中的结构分支与循环语句

    javascript基础入门之js中的结构分支与循环语句 程序的结构①顺序结构:自上而下:②选择(分支)结构:多条路径,根据不同的条件,只执行其中一个:③循环结构:重复某些代码④配合特定的语句实现选择 ...

随机推荐

  1. js里一些经典的算法

    //1.找出某个数字在一组数组内的存不存在 如果存在 找出他所在的索引. function indexOf(arr,item){ var i; if(Array.prototype.indexOf){ ...

  2. ASP.NET MVC 4 批量上传文件

    上传文件的经典写法: <form id="uploadform" action="/Home/UploadFile" method="post& ...

  3. Samba服务详解

    Samba文件服务器 本章结构 服务简介 SMB协议 Server Message Block,服务消息块 CIFS协议 Common Internet File System,通用互联网文件系统 S ...

  4. 转:XMPP协议、MQTT协议、HTTP协议、CoAP协议的基本比较

    一.先看下相关国外的专业数据对四大协议的比较: Protocol                                    CoAP                         XMP ...

  5. MTKLogger日志记录打开

    MTKLogger在 拨号界面用*#446633#(不同手机可能设置不一样) 向左滑动到Log and Debugging下面有个MTKLogger,点进去 点击右上角进入设置,打开MobileLog ...

  6. Javascript之登陆验证

    匹配中文字符的正则表达式: [\u4e00-\u9fa5] 匹配双字节字符(包括汉字在内):[^\x00-\xff] 匹配空行的正则表达式:\n[\s| ]*\r 匹配网址URL的正则表达式:http ...

  7. HTML+CSS学习笔记 (7) - CSS样式基本知识

    HTML+CSS学习笔记 (7) - CSS样式基本知识 内联式css样式,直接写在现有的HTML标签中 CSS样式可以写在哪些地方呢?从CSS 样式代码插入的形式来看基本可以分为以下3种:内联式.嵌 ...

  8. ios 解析json,xml

    一.发送用户名和密码给服务器(走HTTP协议) // 创建一个URL : 请求路径    NSString *urlStr = [NSString stringWithFormat:@"ht ...

  9. JavaScript 函数的执行过程

    每一个JavaScript函数都是Function对象的一个实例, 它有一个仅供JavaScript引擎存取的内部属性[[Scope]]. 这个[[Scope]]存储着一个作用域的集合, 这个集合就叫 ...

  10. 编辑器笔记——sublime text3 编译sass

    如已经安装sass 和 sass build两个插件到ST,command+b编译也没有问题,那么另外安装koala,在koala中引入你要编辑的sass,并把该sass文件设置为自动编译,那么用ST ...