javaScript事件-读书笔记(四)

事件

        javascript与HTML之间的交互是通过事件实现的。事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间。可以使用侦听器(或处理程序)来预定事件,以便事件发生时执行相应的代码。这种在传统软件工程中被称为观察者模式,支持页面的行为与页面的外观之间的松散耦合。

事件流

 事件流描述的是从页面中接收事件的顺序。IE的事件流是事件冒泡流,Netscape的事件流是捕获流。

事件冒泡

event bubbling,即事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点。以下HTML为例:

<html>
    <head>
          <title> event bubbling example </title>
    </head>
    <body>
          <div id="myDiv"> click me </div>
    </body>
</html>

如果点击了页面中的div元素,那么这个click事件会按照如下顺序传播:

  1. <div>
  2. <body>
  3. <html>
  4. document

       也就是说,click事件首先在div元素上发生,而这个元素就是我们单机的元素,然后click事件沿DOM树向上传播,在每一级节点上都会发生,直到传播到document对象。

事件捕获

        event capturing,事件捕获的思想是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件。事件捕获的用意在于在事件到达预定目标之前捕获它。仍以上面的HTML为例,那么单击div元素就会以下列顺序触发click事件:

  1. document
  2. html
  3. body
  4. div

       在事件捕获过程中,document对象首先接收到click事件,然后事件沿DOM树依次向下,一直传播到事件的实际目标。

  1.  

DOM事件流

        DOM2级事件规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。首先发生的是事件捕获,为截获事件提供了机会,然后就是实际的目标接收到事件,最后一个阶段是冒泡阶段,可以在这个阶段对事件作出响应。

        在DOM事件流中,实际的目标在捕获阶段不会接收到事件,这意味着在捕获阶段,事件从document到html再到body后就停止了,下一个阶段是“处于目标”,于是事件在div上发生,并在事件处理中被看成冒泡阶段的一部分,然后,冒泡阶段发生,事件又传播回文档。

        Opera,Firefox,Chrome,safari都支持dom事件流,但是IE不支持DOM事件流。

事件处理程序

        事件就是用户或者浏览器自身执行的某种动作(如click或mouseover等),而相应某个事件的函数就是事件处理程序(或事件侦听器)。

HTML事件处理程序

        某个元素支持的每种事件,都可以使用一个与相应的事件处理程序同名的HTML特性来指定。这个特性的值应该是能够执行的javascript代码。例如,

      <input type="button" value="click" οnclick="alert('clicked me')" />

        或者使用页面外部定义的脚本或者引用外部文件中已定义好的函数。

      <script type="text/javascript">
           function showMessage() {
               alert("click me");
           }
      </script>
      <input type="button" value="click" οnclick="showMessage" />

        不过在HTML中指定事件处理程序有两个缺点。首先,存在一个时差问题。其次是HTML和javascript代码紧密耦合。
 

DOM0级处理程序

        将一个函数赋值给一个事件处理程序属性,具有简单和跨浏览器的优势。

         每个元素都有自己的事件处理程序属性,通常全部小写,例如:

        var btn = document.getElementById('divId');
            btn.onclick = function() {
                alert('click');
            }

        通过DOM0级方法指定的事件处理程序被认为是元素的方法,运行在元素的作用域内,程序中的this引用当前元素。

        删除通过DOM0级方法指定的事件处理程序,只需给事件属性赋值为null即可,如下:

        btn.onclick = null

 

DOM2级处理程序

        DOM2级定义了2个方法,用于处理指定和删除事件处理程序的操作:addEventListener和removeEventListener。所有DOM节点都包含这两个方法,并且接受三个参数:要处理的事件名,作为事件处理的函数和一个boolean值。最后一个参数如果是true表示在捕获阶段调用事件处理程序;false表示在冒泡阶段调用事件处理程序。示例代码如下:

	var btn = document.getElementById('buttonId');
	btn.addEventListener('click',function() {
    		alert('dom add event');
	},false);

        通过addEventListener添加的事件只能使用removeEvnetLisenter来移除,传入的参数和add方法一样。这意味着用addEventListener添加的匿名函数将无法移除。

	var btn = document.getElementById('buttonId');
	var handler = function() {
  		alert(this.id);
	};

	btn.addEventListener('click',handler,false);

	btn.removeEventListener('click',handler,false);

        大多数情况下,都是将事件处理程序添加到事件流的冒泡阶段,这样可以最大限度的兼容各大浏览器。

IE事件处理程序

        IE实现了与DOM中类似的两个方法:attachEvent和detachEvent,这两个方法接受相同的参数:事件处理程序名称和事件处理程序函数。由于IE只支持事件冒泡,所以通过attachEvent添加的事件处理程序都会被添加在事件冒泡阶段。示例如下:

	var btn = document.getElementById('buttonId');
		var handler = function() {
  			alert(this.id);
		};
	//添加click事件
	btn.attachEvent('onclick',handler);
	//移除click事件
	btn.detachEvent('onclick',handler);

        在使用DOM0级方法时,事件处理程序会在其所属元素的作用域内运行,但是在使用attachEvent方法添加的事件处理程序会在全局域中运行,即此刻的this==window。

跨浏览器的事件处理程序

        为了以跨浏览器方式处理事件,保证事件处理程序能够在大多数的浏览器中一致的运行,需要使用能力检测方式编写代码。

	var EventUtil = {
		addHandler: function(element,type,handler) {
				if (element.addEventListener) {
						element.addEventListener(type,handler,false);
				}else if (element.attachEvent){
						element.attachEvent(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(type,handler);
				} else {
						element['on' + type] = null;
				}
				
		}
	}

实例代码:

	var btn = document.getElementById('buttonId');

	var handler = function() {
		alert("clicked me");
	};

	EventUtil.addHandler(btn,'click',handler);
	//移除事件
	EventUtil.removeHandler(btn,'click',handler);

 

事件对象

        在触发DOM上的某个事件时,会产生一个事件对象EVENT,这个对象中包含着所有与事件有关的信息。包括导致事件的元素,事件的类型,以及其他与特定事件相关的信息。

DOM中的事件对象

        兼容DOM的浏览器都会将一个event对象传入到事件处理程序中,无论指定事件处理程序时使用什么方法,都会传入event对象。

	var btn = document.getElementById('buttonId');
	btn.οnclick= function(event) {
		alert(event.type); //click
	};

	btn.addEventListener('click',function(event) {
		alert(event.type);//click
	},false);

event对象属性和方法

event对象属性和方法
属性和方法类型读/写描述
bubblesBoolean只读表明事件是否冒泡
cancellableBoolean只读表明是否可以取消事件的默认行为
currentTargetElement只读事件处理程序当前正在处理事件的那个元素
eventPhaseInteger只读调用事件处理程序的阶段
preventDefaultFunction只读取消事件的默认行为
stopPropagationFunction只读取消事件的进一步捕获或冒泡
targetElement只读事件的目标
typeString只读被触发的事件的类型
detailInteger只读与事件相关的细节信息

        在事件程序处理内部,对象this始终等于currentTarget的值,而target则只包含事件的实际目标。

        要阻止特地给事件的默认行为,可以使用preventDefault方法。例如阻止链接导航的默认行为

	link.onclick =function(event) {
		event.preventDefault();
	}

        只有cancelable属性设置为true的事件,才可以使用preventDefault来取消其默认的行为。

        eventPhase:确定事件当前正处于事件流的哪个阶段。1:捕获阶段;2:处于目标;3:冒泡阶段。

IE中的事件对象

IE中的event对象有几种形式,取决于指定事件处理程序的方法。在使用DOM0级方法添加事件处理程序,event对象作为window对象的一个属性存在,event = window.event;如果是使用attachEvent方法添加的事件处理程序,那么event对象作为参数被传入到事件处理函数中,和dom方式保持一致。

 

IE中的event对象和属性
属性/方法类型读写描述
cancelbubbleBoolean读/写默认值为false,true表示可以取消事件冒泡(与dom中的stopPropagation作用相同)
returnValueBoolean读/写默认值为true,false表示取消事件的默认行为(与dom中的preventDefault作用相同)
srcElementElement只读事件的目标(与dom中的target相同)
typeString只读被触发的事件类型

returnValue:作用是取消事件的默认行为,只要将其设置为false就可以阻止默认行为

var link = document.getElementById('linkId');

link.onclick =function(event) {
		event.returnValue = false;
}


 

跨浏览器的事件对象

虽然DOM和IE中的event对象不同,但是基于他们之间的相似性质可以拿到跨浏览器的方案。IE中的event的全部信息和方法DOM对象中都有,只是实现方式不一样而已。

	var EventUtil = {
		addHandler: function(element,type,handler) {
				if (element.addEventListener) {
						element.addEventListener(type,handler,false);
				}else if (element.attachEvent){
						element.attachEvent(type,handler);
				}else {
					element['on' + type] = handler;
				}
		},
		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;
			}
		},
		
		removeHandler: function(element,type,handler) {
				if (element.removeEventListener) {
						element.removeEventListener(type,handler,false);
				} else if(element.detachEvent) {
						element.detachEvent(type,handler);
				} else {
						element['on' + type] = null;
				}
				
		},
		stopPropagation: function(event) {
			if (event.stopPropagation) {
					event.stopPropagation();
			} else {
					event.cancelBubble = true;
			}
		}
	}

 

待续。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值