`
mutongwu
  • 浏览: 448503 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

事件的侦听、移除和事件对象解析

阅读更多
Javascript的事件处理模型依据不同的浏览器而有所区别,主要分两种:
1.Firefox,Chrome,Safira支持的DOM Level 2事件模型;
2.IE自己的事件处理模型。
而 DOM Level 0 则是所有浏览器都支持的事件机制,但是在IE以及其它支持DOM Level 2的浏览器中,表现仍然有不同。以下代码在IE6,Firefox 3.0中运行通过。

一。DOM Level 0的事件模型:
1.事件的注册方式为使用 on + 事件名=function(){};
2.事件的移除方式为 on + 事件名 = null;
3.处理函数中,this 指向目标对象本身;
4.同一个事件只支持一个处理函数;
5.浏览器差别:
(1)在FF中,事件本身会作为参数传递给处理函数;
(2)在IE中,事件是作为window的一个变量存在,处理函数里面可以通过window.event访问;
(3)event对象所具有的属性随浏览器的不同而不同:IE拥有自己的事件属性,其它浏览器则使用DOM Level 2的事件属性

var btn = document.getElementById('btn');
btn.onclick=function(e){
	//FF中的输出:[object MouseEvent],undefined
	//IE中的输出:undefined,object
	alert(e);
	alert(window.event);
	alert(this == btn);//true
}
//事件的移除
btn.onclick = null;


二。DOM Level 2 的事件模型

1.支持捕获阶段和冒泡阶段的事件处理。 事件流程如下图:


2.事件的注册、移除分别使用addEventListener和removeEventListener
       /* HTML 片段
       <button id='btn'>go</button>
	*/

	var btn = document.getElementById('btn');
	//addEventListener的第三个参数设置为 true,则侦听器只在捕获阶段处理事件,
	//如果为false,则侦听器只在目标或冒泡阶段处理事件。
	btn.addEventListener('click',function(event){
		alert(event.eventPhase);//2
	},false);
	document.body.addEventListener('click',function(event){
		alert('document.body.addEventListener: True:'  + event.eventPhase);//1
		
	},true);
	document.body.addEventListener('click',function(event){
		alert('document.body.addEventListener: '  + event.eventPhase);//3
	},false);

3.尽管目标对象处在冒泡阶段,但是它的eventPhase值为2。
4.取消事件的进一步传递,可以在任一阶段使用
event.stopPropagation();
5.通过 addEventListener方法添加的事件,只能通过removeEventListener进行消除,也就是说,不能通过on + 事件名取消
6.支持对同一事件注册多个事件函数;
7.removeEventListener不能消除匿名事件函数。
	btn.removeEventListener('click', function(){ //won ’ t work!
		alert(this.id);
	}, false);
	
	var handler = function(){
		alert(this.id);
	};
	btn.addEventListener('click', handler, false);
	//other code here
	btn.removeEventListener('click', handler, false); //works!

8.事件本身将作为参数传递给处理函数。
9.在事件处理函数里面,this 恒等于属性currentTarget,target则指向触发事件的最终对象.
       //当body中的一个button被单击的时候
	document.body.addEventListener('click',function(event){
		alert(event.currentTarget === document.body); //true
		alert(this === document.body); //true
		alert(event.target === document.getElementById('btn')); //true
	},false);

10.常用事件对象属性列表:



三。IE的事件模型
1.IE仅支持冒泡阶段的事件处理;
2.事件的注册、移除分别使用attachEvent和detachEvent;
3.处理函数的作用域为window。
btn.attachEvent('onclick',function(event){
		alert(event.type);//"click"
		alert(this === window); //true
		alert(window.event.type);//"click"
});

4.取消事件的进一步传递,可以使用
[window.]event.cancelBubble = true;

5.常用事件对象属性列表:



四。由于事件模型的不同,我们使用以下简单代码,用于跨浏览器的处理。
var EventUtil = {
    addHandler: function(element, type, handler){
	    if (element.addEventListener){
	        element.addEventListener(type, handler, false);
	    } else if (element.attachEvent){
	        element.attachEvent('on' + type, handler);
	    } else {
	        element['on' + type] = handler;
	    }
    },
	removeHandler: function(element, type, handler){
		if (element.removeEventListener){
			element.removeEventListener(type, handler, false);
		}
        else if (element.detachEvent){
		  element.detachEvent('on' + type, handler);
		}
        else {
		  element['on' + type] = null;
		}
	},
	getEvent: function(event){
		return event ? event : window.event;
	},
	getTarget: function(event){
		return event.target || event.srcElement;
	},
	preventDefault: function(event){
		if (event.preventDefault){
			event.preventDefault();
		} else {
			event.returnValue = false;
		}
	},
	stopPropagation: function(event){
		if (event.stopPropagation){
			event.stopPropagation();
		} else {
			event.cancelBubble = true;
		}
	},
	getRelatedTarget: function(event){
		if (event.relatedTarget){
	    	return event.relatedTarget;
		} else if (event.toElement){
	    	return event.toElement;
		} else if (event.fromElement){
	    	return event.fromElement;
		} else {
	    	return null;
		}
	},
	getButton: function(event){
		if (document.implementation.hasFeature('MouseEvents', '2.0')){
		   return event.button;
		}
	    else {
			switch(event.button){
				case 0:
				case 1:
				case 3:
				case 5:
				case 7:
				return 0;
				case 2:
				case 6:
				return 2;
				case 4:
				return 1;
				}
		}
	},
	getCharCode: function(event){
		if (typeof event.charCode == 'number' && event.charCode > 0){
			return event.charCode;
		}
		else {
			return event.keyCode;
		}
	}
};

一个简单的使用例子:
var btn = document.getElementById('myBtn');
var handler = function(){
	alert('Clicked');
};
EventUtil.addHandler(btn, 'click', handler);
//other code here
EventUtil.removeHandler(btn, 'click', handler);



五。以下是常用事件对象的小结

1.获取事件触发的位置
//相对于页面的横向(从左到右)、纵向(从上到下)坐标
clientX,clientY
//相对于显示屏幕的横向(从左到右)、纵向(从上到下)坐标
screenX,screenY

2.判断是否同时有辅助键按下:
var div = document.getElementById('myDiv');
EventUtil.addHandler(div, 'click', function(event){
	event = EventUtil.getEvent(event);
	var keys = new Array();
	if (event.shiftKey){
	    keys.push('shift');
	}
	if (event.ctrlKey){
	    keys.push('ctrl');
	}
	if (event.altKey){
	    keys.push('alt');
	}
        //IE不支持
	if (event.metaKey){
	    keys.push('meta');
	}
	alert('Keys: ' + keys.join(','));
});


3.关于鼠标事件:
3.1 对于mouseout以及mouseover事件,事件发生的时候,可以获取到"相关联的对象"。
例如下面的代码:
< html >
< head >
< title > Related Elements Example < /title >
< /head >
< body >
< div id='myDiv' style='background-color:red;height:100px;width:100px;' > < /div >
< /body >
< /html>

当鼠标从myDiv移动到其它区域(body),mouseout事件触发,那么,相关联的对象就是 body.
当鼠标从其它区域(body)移动到myDiv,mouseover事件触发,那么,相关联的对象就是myDiv.
对于支持 DOM Level 2的浏览器,事件的相关联对象可以从 relatedTarget属性获得;IE则是通过fromElement,toElement来获取。

var div = document.getElementById('myDiv');
EventUtil.addHandler(div, 'mouseout', function(event){
	event = EventUtil.getEvent(event);
	var target = EventUtil.getTarget(event);
	var relatedTarget = EventUtil.getRelatedTarget(event);
	alert('Moused out of ' + target.tagName + ' to ' + relatedTarget.tagName);
});

3.2 对于mousedown和mouseup事件,触发时候,可以获取到button属性。对于支持DOM Level2模型的浏览器,button的取值为:0:左键;1:中键(滚轮);2:右键
对于IE,有自己的许多取值,具体含义如下:



通常,我们只需要区别是鼠标的哪一个按键就已经足够了。
整合以后的代码见EventUtil。

4.键盘事件
4.1 键盘支持3种事件:
keydown:当任一按键被按下的时候;
keypress:当任一字符按键按下的时候(也包括Esc按键);
keyup:当任一按键松开的时候;
4.2 如果一个字符按键一直被按下,那么keydown、keyress事件将重复触发;
如果是一个非字符按键一直被按下,那么keydown事件将重复触发。
通常,keydown、kepress事件将在输入框内容变化之前触发,keyup将在输入框内容变化之后触发。
这也就说明,我们可以在keydown或者keyress事件处理中取消其向后传递,从而实现屏蔽掉一些字符的输入。
键盘上的keyCode的值如下表,对于数字和字母根据ASCII表取值。





注意:
对于keydown和keyup事件,字母(A~Z)的charCode取值为0,keyCode则是字母(大写)的ASCII值。例如 a 与 A的keyCode相同。
另外,对于分号 ';'Firefox与Safira返回其在ASCII码表里面的值59;IE,Chrome则返回值186。

4.3 当keypress事件触发时候,对于Firefox,Chrome,Safari,通过event的一个属性charCode来获取(此时keyCode值为0),IE和Opera则使用keyCode。
获取到keyCode以后,则可以通过String.fromCharCode()来获取字符
//只允许退格键和数字输入
var textbox = document.getElementById('myText');
	EventUtil.addHandler(textbox, 'keypress', function(event){
		event = EventUtil.getEvent(event);
		/*直接通过event.keyCode返回数字。即字母在ASCII表值。区分大小写。
		ff 与 chrome都是返回0.
		如果在ff与chrome中返回 event.charCode,将是字母在ASCII表值。区分大小写。*/
		var code = EventUtil.getCharCode(event);
		//alert(code);
		var ch = String.fromCharCode(code);
		//alert('Unicode:' + ch);
		if(ch != 8 && (ch < '0' || ch > '9')){
			EventUtil.preventDefault(event);
		}		
	});
[/size]

4.4 keydown(keyup)事件触发的时候与 keypress有所不同。
	EventUtil.addHandler(btn, 'keyup', function(event){
		event = EventUtil.getEvent(event);
		/*直接通过event.keyCode返回数字,字符A与字符a都返回65,即字母都是ASCII表对应的大写字母的值。
		如果在ff与chrome中返回 event.charCode,同样不区分大小写。值为大写字母的值 。*/
		var code = EventUtil.getCharCode(event);
		alert(code);
		var ch = String.fromCharCode(code);
		alert(ch);	
	});

整理自《Professional.JavaScript.for.Web.Developers.2nd.Edition》,有修改。
  • 大小: 43.1 KB
  • 大小: 12.9 KB
  • 大小: 30.1 KB
  • 大小: 38.3 KB
  • 大小: 38.1 KB
  • 大小: 55.6 KB
分享到:
评论

相关推荐

    侦听矢量图层要素的事件1

    GeoJSON是一种常见的地理数据格式,可以表示点、线和多边形等几何对象。在这里,我们使用`defaultDataProjection`来指定数据的坐标系。 为了与图层中的要素进行交互,我们创建了一个`ol.interaction.Select`实例,...

    ActionScript 3.0 开发人员指南 (AS3开发帮助文档)

    **响应错误事件和状态** 除了同步错误之外,还有一类异步错误,它们通常是通过事件来触发的。开发者需要监听特定的错误事件并作出响应。 **比较错误类** 理解不同错误类之间的区别可以帮助开发者更有效地诊断问题...

    ActionScript 3.0 开发人员指南中文官网上下的

    - **响应错误事件和状态**:通过监听特定的错误事件可以更好地管理错误。 - **处理错误示例**:CustomErrors 应用程序演示了如何优雅地处理各种类型的错误。 #### 五、使用正则表达式 - **正则表达式基础知识**:...

    ActionScript3.0开发人员指南

    - **事件流**:详细解析事件的传播过程,即捕获阶段、目标阶段和冒泡阶段,以及如何利用这些阶段进行事件处理。 - **事件对象**:讲解`Event`对象的作用,包括如何访问事件的属性和方法。 - **事件侦听器**:教授...

    actionScript学习文档

    - **响应错误事件和状态**:讲解如何根据不同的错误事件和状态做出响应。 - **比较错误类**:对比不同错误类的特点及适用场景。 - **处理错误示例**:通过一个具体的示例,演示如何在实际项目中处理错误。 #### 六...

    30 道 Vue 面试题,内含详细讲解(涵盖入门到精通,自测 Vue 掌握程度)

    对象语法允许根据数据状态添加或移除类,数组语法可以组合多个类。 - `v-bind:style`同样支持对象和数组语法,用于动态设置样式。对象语法可直接设置样式属性,数组语法可以组合多个样式对象。 4. **Vue的单向数据...

    vue面试题.2023

    - 对象语法:根据变量值动态添加或移除类名。 - 数组语法:根据数组内容决定要应用的类名列表。 - **Style动态绑定**:同样支持对象和数组语法,动态设置CSS样式。 - 对象语法:键值对形式,根据变量动态设置...

    Portal教程

    - **书籍**:《IBM WebSphere Portal Handbook》、《Developing Portlets with IBM WebSphere Portal》等,深入解析Portal技术原理和最佳实践。 总之,Portal技术不仅提供了一个强大的平台来构建复杂的Web应用,还...

    day01.pdf vuejs

    Vue.js 还提供了丰富的指令系统,如条件渲染的`v-if`和`v-show`,循环渲染的`v-for`,事件处理的`v-on`,以及计算属性和侦听器等。这些工具使开发者能更高效地构建复杂的用户界面,同时保持代码的简洁和可维护性。 ...

    牛客前端面试高频八股总结(2)

    **Computed**(计算属性)和 **Watch**(侦听器)都可以用来监听数据的变化,但它们的用途和特性有所不同: - **Computed**:基于依赖进行缓存,依赖的数据未变化时不会重新计算。 - **Watch**:不具有缓存机制,...

    zigbee2004协议使用手册(PK).pdf

    ### ZigBee2004协议使用手册知识点详解 #### 一、ZigBee简介 ...通过以上对ZigBee2004协议使用手册的解析,我们可以了解到ZigBee协议栈的具体组成及其各层的主要功能,这对于理解和应用ZigBee技术至关重要。

    Flash脚本代码大全

    20. **On Clip Event(侦听剪辑事件)** - 功能:侦听剪辑上的事件。 - 示例:`onClipEvent (load) { /* 当剪辑加载时执行的代码 */ }` 21. **Remove Movie Clip(删除电影片段)** - 功能:从舞台上删除一个...

    Linux编程白皮书

    - **页换出和淘汰**:当内存不足时,选择哪些页面从内存中移除的过程。 - **交换缓存**:专门用于缓存交换数据的数据结构,以提高交换操作的效率。 - **页换入**:将先前交换出去的页面重新加载回内存的操作。 ##...

    vue学习笔记之vue1.0和vue2.0的区别介绍

    - **计算属性和侦听器的优化**:Vue 2.0 对计算属性和侦听器的实现进行了优化,提供了更好的性能和控制。 - **单一文件组件(SFC)**:Vue 2.0 推广了单一文件组件格式,使得样式、模板和逻辑可以在同一个文件中组织...

    后端api采用go语言框架gin编写,前端使用vue + element ui编写.zip

    例如,可以使用`c.ShouldBind`来将请求体自动解析并绑定到模型对象。 5. **错误处理**:Gin允许开发者自定义错误处理,通过`c.AbortWithError`停止处理并返回错误。 接下来,我们转向前端部分,Vue.js是一个轻量级...

Global site tag (gtag.js) - Google Analytics