欢迎来到 jackNEss'窝窝
I like simple mind

talk about onmouseEnter & onmouseLeave

2011年10月10日

talk_about_onmouseenter_onmouseleave

或许有部分童鞋对这 1对璧人、额不对 一对事件 有点陌生 不过如果有接触过jquery的人应该会知道 这2个事件,意思就像字面般 onmouseenter(鼠标进入)、onmouseleave(鼠标离开),那和 onmouseover(鼠标经过)、onmouseout(鼠标离开)有什么区别呢,这 2 个方法其实并不在 ecmascript 里头,而是 IE 里面的 私有方法,那为什么还要在这里花篇幅去介绍呢,因为…因为在开发的过程中会遇到的(总有那么的一次,总有那么的一天),在这里主要是给大家分析一下这 2 个事件的原理与实现方法。

onmouseenter & onmouseleave 与
onmouseover & onmouseout 的区别

在叙述他们的区别之前,我们先看一个例子,下面贴一下关键部分代码:

<-- html 部分 -->
<div class="parent" id = "parent">
	<div class="child">
		<div class="child">
			<div class="child">
				<div class="child">
					<div class="child">
						<div class="child" id = "txt">
							靠近我试试<br/>有惊喜哦
						</div>
					</div>
				</div>
			</div>
		</div>
	</div>
</div>	

现在分别通过 js给 上面 html 的 .parent 绑定事件 —— 鼠标经过 #parent 时 统计触发鼠标经过的计数器自加1,鼠标离开 #parent 时 统计触发鼠标离开的计数器自加1。分别用 onmouseenter & onmouserleave 和 onmouseover & onmouseout 事件来实现:

//绑定 onmouseover & onmouseout	
var par = document.getElementById("parent");
var txt = document.getElementById("txt");
var overNum = 0,outNum = 0;
par.onmouseover = function(){
	overNum++;
	//输出统计信息
	txt.innerHTML = "触发 onmouseover 次数:"+ overNum +"<br/>触发 onmouseout  次数:" + outNum;
}
par.onmouseout = function(){
	outNum++;
	//输出统计信息
	txt.innerHTML = "触发 onmouseover 次数:"+ overNum +"<br/>触发 onmouseout  次数:" + outNum;
}
//绑定 onmouseenter & onmouseleave
var par = document.getElementById("parent");
var txt = document.getElementById("txt");
var enterNum = 0,leaveNum = 0;
par.onmouseenter = function(){
	enterNum++;
	//输出统计信息
	txt.innerHTML = "触发 onmouseenter 次数:"+ enterNum +"<br/>触发 onmouseleave  次数:" + leaveNum;
}
par.onmouseleave = function(){
	leaveNum++;
	//输出统计信息
	txt.innerHTML = "触发 onmouseenter 次数:"+ enterNum +"<br/>触发 onmouseleave  次数:" + leaveNum;
}

演示地址:http://www.jackness.org/lab/onmouseenter_onmouseleave/demo01.html

我们发现:
当鼠标移动到 “靠近我试试” 的时候, 绑定 onmouseover 和 onmouseout 事件的 那个例子 onmouseover 触发了 7 次,而 onmouseout 触发了 6 次;而绑定 onmouseenter 和 onmouseleave 事件的 那个例子 onmouseenter 触发了 1 次,onmouseleave 触发了 0 次。

为什么会这样子呢,这个就牵涉到 事件冒泡 这一概念了,onmouseenter 与 onmouseover 的区别在于: onmouseenter 自带阻止事件冒泡,而onmouseover没有。同理 onmouseleave也是如此。

需要 onmouseenter & onmouseleave 的地方

onmouseenter & onmouseleave 这一概念其实在平常功能实现的过程中都经常用到,不过有些时候部分的功能不需要太过精准而直接用 onmouseover & onmouseout代替了事。

在这里我就拿某项目中要运用到 onmouseenter 和 onmouseleave 这概念的 一个小功能来分析一下 。

首先我们接到这样一个功能需求:

如图所示,有这么一个用户头像,当鼠标滑过头像的时候,显示出详细信息,当鼠标离开那带有详细信息的图层时,该层隐藏。

根据需求, html部分 我们这样来布局:

<!-- 图片层 -->
<img id = "img" src="http://www.jackness.org/wp-content/themes/JStyle/images/default/blank.png" _src="xxx.jpg" alt=""/>

<!-- 带有图片的详细信息层 -->
<div id = "card_box">
	<!-- 左侧 -->
	<div>
		<img src="http://www.jackness.org/wp-content/themes/JStyle/images/default/blank.png" _src="xxx.jpg" alt=""/>
	</div>
	
	<!-- 右侧 -->
	<div>
		文字信息部分
	</div>
</div>

然后根据需求作功能分析:

当鼠标移向 #img 的时候, #card_box 的 display = “block”;
当鼠标离开 #card_box 的时候, #card_box 自己 display = “none”;

接着编写功能所需的 js:

var img = document.getElementById("img");
var card_box = document.getElementById("card_box");

img.onmouseover = function(){
	card_box.style.display="block";
}
card_box.onmouseout = function(){
	this.style.display="none";
}	
	

演示地址:http://www.jackness.org/lab/onmouseenter_onmouseleave/demo02_1.html

很遗憾,我们发现,当鼠标移到 #img 上方时, #card_box 出现,到这里为止还是没问题的,但是如果我想移到 详细信息框右侧的 超链接处的时候,发觉,只要鼠标一离开 图像范围, #card_box 就会隐藏起来了,达不到预期的效果。

这是由于:
每当鼠标从子元素A 移到子元素B 的时候所触发的 onmouseover 和 onmouseout 都冒泡到 父元素 #card_box 的 onmouseover 和 onmouseout 上面,从而触发 #card_box 对应的事件。

这就是事件冒泡所引起的经典问题之一,解决方法是 引入 onmouseenter 和 onmouseleave概念,通过模拟 这 2 个事件来将问题解决。

onmouseenter & onmouseleave 原理

只有了解这2个事件的原理,才能在日后遇到相同情况的时候快速的解决问题。(what? 你用 jquery…有现成?嗯,那你就用jquery吧)

onmouseenter

onmouseenter 的意思就是 进入元素的时候触发,即进入A对象时触发一次,但是在A对象里面无论鼠标经过A对象里面的任何对象,这个事件都不会被触发。

原理:

假定用 onmouseover事件来模拟 onmouseenter,由于涉及事件冒泡,每当鼠标在A对象里头游走于A对象中的 各个子元素的时候事件都会被触发(从A对象里面的 A-a1对象移动到 A-a2或者 A 对象时均会触发 onmouseover 事件),所以,我们要在触发 onmouseover 事件的时候 加一个判断:判断当前触发事件的事件源与 A对象是什么关系,若 事件源是 A对象或者是A对象的子元素的话,那么return, 不触发事件。

onmouseleave

onmouseleave 的意思就是 离开元素的时候触发,即当元素离开A对象到其他 非A对象的时候(这个非A对象并不包括 A的所有子对象or A 自己本身)时触发一次,否则 事件不触发。

原理:

假定用 onmouseout事件来模拟 onmouseleave,由于涉及事件冒泡,每当鼠标在A对象里头游走于A对象中的 各个子元素的时候事件都会被触发(从A对象里面的 A-a1对象移动到 A-a2或者 A 对象时均会触发 onmouseout 事件),所以,我们要再触发 onmouseout 事件的时候加一个判断:判断当前触发事件的事件源与 A对象是什么关系,若 事件源 是 A对象或者A对象的子元素的话,那么 return,不触发事件。

下面是判断 2 者关系的一小段 js,当然实现的方式是各种各样的:

//判断 parent 与 child 是否有联系(子集或者是 parent本身)
function isRelative(parent,child){
	if( parent == child){ 
		return true;
	}
	var childs = parent.getElementsByTagName("*");
	for( var i = 0; i < childs.length; i++){
		if( childs[i] == child){
			return true;
		}
	}
	return false;
}

模拟 onmouseleave 事件

知道了原理,前面所举的那个例子的问题就自然地解决方案就出来了,下面是模拟 onmouseleave部分的代码:

card_box.onmouseout = function(e){
	e = e||window.event;
	var _targetElement = document.elementFromPoint(e.clientX,e.clientY);
	
	//调用上面所写的 isRelative() 方法判断关系
	if( !isRelative(this,_targetElement) ){
		this.style.display = "none";
	}
}	

演示地址:http://www.jackness.org/lab/onmouseenter_onmouseleave/demo02_2.html

至于 模拟 onmouseenter 事件,和 模拟onmouseleave同理,在此就省略 x00 字加以叙述了。

分类javascript
阅读 1,372
  • 评论加载中...

标签云

分类目录

最新留言

  • 评论加载中...

与我联系

如有疑问or建议可通过以下方式跟我取得联系.

Q Q:373435871
Email:jackness1208@gmail.com
© Copyright 2011 - 2014 jackNEss.org All Rights Reserved 粤ICP备14065612号
首页 | 关于我 | 网站地图 | RSS