【js学习笔记-092】-----事件处理程序的调用

来源:互联网 发布:java反射获取私有属性 编辑:程序博客网 时间:2024/05/29 10:27

事件处理程序的调用

接下来会详细介绍事件处理程序的调用,说明事件处理程序的参数,调用上下文、调用作用域和事件处理程序返回值的意义。遗憾的是,这些内容中的一部分在IE8及以前版本中和其他浏览器中是不同的

 

事件处理程序的参数

调用事件处理程序时把事件对象作为它们的一个参数。事件对象的属性提供了有关事件的详细信息。例如type属性指定了发生的事件类型。

IE8及以前版本中,通过设置全局对象 window.event来获得事件对象。程序的通用写法如下

function handler(event){

   event = event || window.event;

}

向使用 attachEvent()注册的事件处理程序传递事件对象,但它们也能使用window.event。

当在html属性注册事件处理程序时,浏览器会把js编码转换到一个函数中。非IE浏览器使用event参数来构造函数,而ie在构造函数时没有要求参数。所以如果这样的函数使用event标识符,那么引用的正是window.event。在这两种情况下,html事件处理程序都能作为evnet引用对象。

 

事件处理程序的运行环境

e.onclick =function(){/*代码*/}

事件处理程序在事件目标上定义,所以它们作为这个对象的方法来调用并不出人意料。就是说,在事件处理程序内,this关键字指的是事件目标

使用addEventListener()注册时,调用的处理程序使用事件目标作为this值。attachEvent()来讲是不对的,使用attachEvent()注册的处理程序作为函数调用,它们的this值是全局对象window对象。可以用如下代码解决

 function addEvent(target,type,handler){

 if(target.addEventListener){

  target.addEventListener(type,handler,false);

}else{

 target.attachEvent(“on”+type,function(event){

  return handler.call(target,event);

});

}

}

注意使用这个方法注册的事件处理程序不能删除,因为传递给attachEvent()的包装函数没有保留下来传递给 detachEvent()。

事件处理程序的作用域

像所有js函数一样,事件处理程序从词法上讲也是作用域。它们在其定义时的作用域而非调用时的作用域中执行,并且它们能存取那个作用域中的任何一个本地变量。

但是,通过html属性注册的事件处理程序是一个例外。它们被转换为能存取全局变量的顶级函数而任何本地变量。

事件处理程序的返回值

在事件处理程序中设置return flase是一种有效的阻止浏览器不要执行这个事件相关的默认操作的方法。

如onbeforeunload事件的返回值,将会以字符串显示在用户是否离开当前页面的标准对话框中

addEventListener()和attachEvent()注册事件处理程序。必须调用preventDefault()方法或设置事件对象的returnValue属性

 

调用顺序

  •   当事件发生时,浏览器必须按照如下规则调用所有的事件处理程序:
  •  通过设置对象属性或html属性注册的处理程序一直优生调用。
  •  使用addEventListener()注册的处理程序按照它们的注册顺序调用
  •  使用attachEvent()注册的处理程序可能按照任何顺序调用,所以代码不应该依赖于调用顺序。

事件传播

在调用在目标元素上注册的事件处理函数后,大部分事件会“冒泡”到DOM树根。调用目标的父元素的事件处理程序,然后调用在目标的祖父元素上注册的事件处理程序。这会一直到Document对象,最后到达Window对象。事件冒泡为在大量单独的文档元素上注册处理程序提供替代方案,即在共同的祖先元素上注册一个处理程序来处理所有的事件。如在form元素上注册onchange事件处理程序来取代在表单的每个元素上注册change事件处理程序。

发生在文档元素上的大部分事件都会冒泡(focus/blur/scroll例外)。文档元素上的load事件会冒泡,但它会在Document对象上停止冒泡而不会传播到window对象。只有当整个文档加载完毕时才会触发Window对象的load事件。

事件的三个阶段:事件捕获、正在事件、事件冒泡。

事件捕获阶段像反向冒泡阶段。最先调用window对象的捕获处理程序,然后Document对象的捕获处理程序,接着是body对象,再然后是dom树向下,以此类推,直到调用事件目标的父元素的捕获事件处理程序。在目标对象本身上注册的捕获事件处理程序不会被调用!!!

事件捕获提供了在事件没有送达目标之前查看它们的机会。事件捕获能用于程序调试,或用于后面介绍的事件取消技术,过滤掉事件从而使目标事件处理程序绝不会被调用。它常用于处理拖放,因为要处理拖放事件的位置不能是这个元素的子元素

 

事件取消

在支持addEventListener()的浏览器中,通过调用事件对象的preventDefault()方法取消事件默认操作。在IE9之前,可以通过设置事件对象的returnValue属性设为false来达到同样的效果。

 //取消默认事件

function  cancelHandler(event){

   var e = event || window.event;

  if(e.preventDefault) e.preventDefault(); //标准技术

  else if(e.returnValue) e. returnValue =false; //IE

  else return false; //用于处理使用对象属性注册的处理程序

}

当前DOM事件模型草案定义了Event对象属性defaultPrevented。它尚未得到广泛支持。常态下这个属性是false。但如果使用preventDefault()被调用。则它将变成true.

阻止冒泡

支持addEventListener()浏览器,可以调用事件对象的一个stopPropagation()方法以阻止事件的继续传播。如果在同一个对象上定义了其他处理程序,剩下的处理程序将依旧被调用。但在调用stopPropagation()之后任何其他对象上的事件处理程序将不会被调用。该方法可以在事件传播的任何时间调用,它能工作在捕获阶段,事件目标本身,冒泡阶段。

IE9之前不支持stopPropagation()方法,相对,IE事件对象有一个cancelBubble属性,设置这个属性为true能阻止事件进一步传播

当前DOM事件规范草案在Event对象上定义另一个方法,命名为stopImmediatePropgation()。类似stopPropagation() 这个方法阻止了任何其他对象的事件传播。但也阻止了在相同对象上注册的任何其它事件处理程序的调用。

0 0
原创粉丝点击