JavaScript 事件流、事件处理程序及事件对象总结

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

一、事件流

事件流描述的是从页面中接受事件的顺序。

事件冒泡

事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的结点(文档)。以下面HTML页面为例,如果你点击了页面中的按钮,那么”click”事件会按照< button>、< body>、< html>、document的顺序传播。换句话说,事件冒泡指的就是事件从底层触发事件的元素开始沿着DOM树向上传播,直到document对象。

<html>
 <head>
  <title>Test</title>
 </head>
 <body>
  <button id="myBtn">A Btn</button>
 </body>
</html>

事件捕获

与事件冒泡的思路相反,事件捕获的思想是不太具体的节点应该更早地接收到事件,最具体的结点应该最后才接收事件。同样还是上面那个例子,点击页面中的按钮之后,”click”事件会按照document、< html>、< body>、< button>的顺序传播。换句话说,事件捕获就是指事件从document对象开始沿着DOM树向下传播,直到事件的实际目标元素。

DOM事件流

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

还是以之前的点击按钮为例,在DOM事件流中,捕获阶段,”click”事件从document开始向下传递到body元素(注意,实际目标button在捕获阶段不会接收到事件)。目标阶段,button元素接收到”click”事件。最后,冒泡阶段,事件又被传播回文档。

二、事件处理程序

事件是用户或浏览器自身执行的某种动作,而响应某个事件的函数就叫做事件处理程序或事件侦听器。

HTML事件处理程序

这里的HTML事件处理程序指的是直接在HTML元素里面通过特性(attribute)定义的事件处理程序,请看下面的代码示例。这样是定的事件处理程序会创建一个封装着元素属性值的函数,this值等于事件的目标元素。通过这种方法指定事件处理程序存在不少缺点,不推荐使用。

<button onclick="alert('HaHa~')">Btn-1</button>
<button onclick="alert('event.type')">Btn-2</button>
<button onclick="handler()">Btn-3</button>
<script type="text/javascript">
 function handler() {
  alert("Haha~");
 }
</script>

DOM0级事件处理程序

通过JS指定事件处理程序的传统方式就是将一个函数赋值给一个事件处理程序属性,请看下面代码示例。通过这种方式指定的事件处理程序是在元素的作用域中运行,this引用的是当前元素。这种方式添加的事件处理程序会在事件流的冒泡阶段被处理。若要删除事件,直接令onclick的值为空即可。

var btn = document.getElementById("myBtn");
btn.onclick = function() {
 console.log("this.id"); // "myBtn"
};
// 删除事件处理程序
btn.onclick = null;

DOM2级事件处理程序

“DOM2级事件”定义了两个方法用于指定和删除事件处理程序,addEventListener()和removeEventListener()。所有DOM节点中都包含这两个方法。这两个方法都接收3个参数,要处理的事件、处理函数、布尔值。最后的布尔值为true时表示在捕获阶段调用事件处理程序,为false时表示在冒泡阶段调用处理程序。与DOM0级方法一样,这里添加的事件处理程序也是在其依附的元素的作用域中运行。DOM2级方法添加事件处理程序的优势是可以添加多个事件处理程序。这些事件处理程序会按照它们被添加的顺序触发。下面是代码示例:

var btn = document.getElementById("myBtn");
// 添加,触发点击事件时先输出"myBtn"再输出"HaHa~"
btn.addEventListener("click", function() {
 console.log(this.id);
}, false);
btn.addEventListener("click", function() {
 console.log("HaHa~");
}, false);

通过addEventListener()添加的事件只能通过removeEventListener()来删除。删除时传入的参数与添加时使用的参数应该保持一致。这也意味着通过addEventListener()添加的匿名函数将无法删除,因为无法将添加时传递的匿名函数传给removeEventListener(),即便在删除的时候写了一个一模一样的函数,但此时这个函数只是一个新的匿名函数。请看下面代码示例:

var btn = document.getElementById("myBtn");
// 无法删除匿名函数
btn.addEventListener("click", function() {
 console.log(this.id);
}, false);
btn.removeEventListener("click", function() {
 console.log(this.id);
}, false);

// 正确的添加和删除方式
function handler() {
 console.log(this.id);
}
btn.addEventListener("click", handler, false);
btn.removeEventListener("click", handler, false);

大多数情况下,都是将事件处理程序添加到事件流的冒泡阶段,这样可以最大限度地兼容各种浏览器。最好只在需要在事件到达目标之前截获它的时候才将事件处理程序添加到捕获阶段。JS高级程序设计上给出的建议是,如果不是特别需要,不建议在事件捕获阶段注册事件处理程序。

IE事件处理程序

IE实现了与DOM中类似的两个方法: attachEvent()和deleteEvent()。这两个方法接收两个参数,事件处理程序名称和事件处理程序。注意,第一个参数是事件处理程序名称而不是事件名称,也就是说在注册点击事件的处理程序时应该传入”onclick”而不是”click”,这里跟DOM的方法有些差别。另外,这两个方法注册的事件处理程序是在全局作用域中运行而不是元素作用域,this的值指向window。还有一点需要特别小心,通过attachEvent()方法也可以添加多个事件处理程序,但是它们的执行顺序却不是按照它们被添加的顺序,而是完全相反,跟DOM方法截然不同。突然觉得IE真的特别反人类~~~下面是代码示例:

var btn = document.getElementById("myBtn");
function handler1() { // ... }
function handler2() { // ... }
// 添加,触发点击事件时先执行handler2再执行handler1
btn.attachEvent("onclick", handler1);
btn.attachEvent("onclick", handler2);
// 删除
btn.deleteEvent("onclick", handler1);
btn.deleteEvent("onclick", handler2);

三、事件对象

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

DOM中的事件对象

兼容DOM的浏览器会将一个event对象传入事件处理程序中,无论指定事件处理程序时用的是DOM0还是DOM2的方法,都会传入event对象。event对象只有在事件处理程序执行期间才会存在,一旦事件处理程序执行完毕,event对象就会被销毁。下面是代码示例:

var btn = document.getElementById("myBtn");
btn.onclick = function(event) {
 console.log(event.type); // "click"
}
btn.addEventListener("click", function(event) {
 console.log(event.type);
}, false);

event对象包含与创建它的特定事件有关的属性和方法,触发的事件类型不一样,可用的属性方法也有所不同。但是所有的事件都会有下列的属性或方法:

  • bubbles: 布尔值,表示事件是否冒泡
  • cancelable: 布尔值,表示是否可以取消事件的默认行为
  • currentTarget: 元素,事件处理程序当前正在处理事件的那个元素
  • defaultPrevented: 布尔值,表示是否调用过preventDefault()方法
  • detail: 整数,与事件相关的细节信息
  • eventPhase: 整数,调用事件处理程序的阶段,1表示捕获阶段,2表示目标阶段,3表示冒泡阶段
  • preventDefault(): 函数,取消事件的默认行为,cancelable为true时可以调用该方法
  • stopImmediatePropagation(): 函数,取消事件的进一步捕获或冒泡,同时阻止任何事件处理程序被调用
  • stopPropagation(): 函数,取消事件的进一步捕获或冒泡,bubbles为true时可以调用这个方法
  • target: 元素,事件的目标
  • trusted: 布尔值,为true时表示事件是浏览器生成的,否则表示事件是通过JS创建的
  • type: 字符串,被触发的事件类型
  • view: 与事件关联的抽象视图,等同于发生事件的window对象

下面代码示例展示了上述部分属性的用法,也可以帮助我们进一步理解事件流。假设页面中有一个按钮”myBtn”。当点击按钮时,this和currentTarget都等于body元素,因为事件处理程序是注册在body元素上。target的值却等于按钮元素,因为它是click事件的真正目标。由于按钮上没有注册事件处理程序,结果”click”事件冒泡到了document.body那里才得到处理。

document.body.onclick = function(event) {
 console.log(event.currentTarget === document.body); // true
 console.log(this === document.body); // true
 console.log(event.target === document.getElementById("myBtn")); // true
};

再看一个例子,下面代码中,stopPropagation()方法取消了事件的进一步捕获或冒泡。当我点击按钮时,本来应该会因为事件冒泡机制触发按钮和body元素上的点击事件处理程序,输出”From Bth …”和”From Body …”。现在点击事件在按钮元素上触发之后就被阻止继续在DOM层次中的传播,因此body上的事件处理程序不会被触发。

var btn = document.getElementById("myBtn");
btn.onclick = function(event) {
 console.log("From Bth ...");
 event.stopPropagation(); // 停止事件传播
};
document.body.onclick = function() {
 console.log("From Body ...");
};

IE中的事件对象

在IE中,使用DOM0的方法添加事件处理程序时,event对象作为window对象的一个属性存在。如果是通过attachEvent()方法添加,则event对象是作为参数传入事件处理函数。下面是代码示例:

var btn = document.getElementById("myBtn");
btn.onclick = function() {
 var event = window.event;
 console.log(event.type); // "click"
};
btn.attachEvent("onclick", function(event) {
 console.log(event.type); // "click"
});

IE的event对象同样也包含与创建它的事件相关的属性和方法,这些属性和方法也会因为事件类型的不同而有所差异。但所有事件对象都会包含下列属性:

  • cancelBubble: 布尔值,可读可写,默认为false。将其设置为true时取消事件冒泡
  • returnValue: 布尔值,可读可写,默认为true。将其设置为false时取消事件的默认行为
  • srcElment: 元素,事件的目标元素,与DOM中的target属性相同
  • type: 字符串,事件类型

在IE中,事件处理程序的作用域是根据指定它的方式来确定,this的值不一定是指向事件的目标元素。因此,使用srcElement属性更具保险。请看下面代码实例,第一种方式中this的值为目标元素,而第二种方式,前面讲过这种方式的事件处理程序是在全局作用域中执行,因此this的值为window。

var btn = document.getElementById("myBtn");
btn.onclick = function() {
 console.log(window.event.srcElement === this); // true
}
btn.attachEvent("onclick", function(event) {
 console.log(event.srcElement === this); // false
});

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持我们!

(0)

相关推荐

  • js 事件对象 鼠标滚轮效果演示说明

    Mouse Wheel Data .slider { width:50px; height:180px; background:#eee; padding:10px 0; cursor:n-resize; } .slider-slot { width:16px; margin:0 auto; height:180px; background:#eee; border:1px solid gray; border-color:#999 white white #999; position:rela

  • Javascript 事件流和事件绑定

    事件流 浏览器中的事件流意味着页面上可有不仅一个,甚至多个元素响应同一个事件.而这一个或多个元素响应事件发生的先后顺序在各个浏览器(主要针对IE和Netscape)上是不同的. 冒泡型事件(Dubbed Bubbling) IE上的解决方案就是冒泡型事件(Dubbed Bubbling).冒泡型事件的基本思想是,事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发. 示例(1):点击我触发冒泡型事件流 示例(1)的XHTML代码结构:<span id="cnt0

  • javascript 事件处理、鼠标拖动效果实现方法详解

    先看看要拖动的层(模拟窗口)的效果图吧. 要实现的拖动效果:鼠标左键在窗口上方的标题栏上按下,同时移动鼠标,窗口跟着移动.窗口: 复制代码 代码如下: <div id="win"> <div id="win_header"></div> </div> 一点准备工作: 要让窗口能自由移动,那么窗口的定位(position)应该采用绝对定位(absolute): 给窗口添加标题栏,这里使用一个放在窗口顶部的层实现,同时将标

  • Ext javascript建立超链接,进行事件处理的实现方法

    1,如何在javasript建立超链接 <script type="text/JavaScript"> //方法一: location.href='网址'; //方法二: document.write('<a href="网址">文字</a>'); </script> 2,应用到Ext中的树控件事件处理 tree_03.js 复制代码 代码如下: Ext.onReady(function(){ var root = n

  • javascript 基础篇3 类,回调函数,内置对象,事件处理

    复制代码 代码如下: function 类名(参数表){ this.属性; ...... this.函数; } 这样,函数和数据成员都是用"this."来实现. 我们自己定义一个简单类student好了,然后再去构造它,并且实现一个输出函数. 复制代码 代码如下: <script LANGUAGE="JavaScript"> <!-- function student(a,b){ this.name = a; this.age=b; this.ou

  • JavaScript实现为指定对象添加多个事件处理程序的方法

    本文实例讲述了JavaScript实现为指定对象添加多个事件处理程序的方法.分享给大家供大家参考.具体如下: 如果你希望对象点击的时候同时处理多个事情,可以使用下面的代码 /* Start of the multihandle Object...*/ function MultiHandle(owner){ var my_handlers = new Array(); var my_owner = owner; this.append = function(handler){ my_handle

  • javascript下对于事件、事件流、事件触发的顺序随便说说

    1.首先我们来了解几个概念,"事件","事件流","事件名称","事件处理函数/事件监听函数,也许是"老生常谈",知道的朋友可以越过. 事件: 事件是用户自身或浏览器进行的特定行为.如:用户点击 也就是常用的click事件 事件流:多个事件 按一定顺序触发 形成了事件流 事件名称:如上面所讲的click就是事件名 事件处理函数/事件监听函数(Dom的叫法)就是 事件触发后的处理函数,如obj.onclick=fn;函

  • js使用函数绑定技术改变事件处理程序的作用域

    第一种,也是 最常见的,就是直接在html标签里面通过指定事件处理程序同名的HTML属性来注册事件,代码如下: 复制代码 代码如下: function eventHandler() { alert("当前作用域是 input 元素本身"); } <input type="button" value="单击我" onclick="eventHandler(this)"/> 第二种方式就是将一个函数赋值给一个事件处理程

  • js中获取事件对象的方法小结

    复制代码 代码如下: var evt = window.event || arguments[0]; 下面分三种添加事件的方式讨论,你也许会看到以前没有看到过的获取方式. 1,第一种添加事件的方式,直接在html的属性中写JS代码 复制代码 代码如下: <div onclick="alert(4);">Div1 Element</div> 大概这是上世纪90年代的写法,那时候直接把js代码写在网页中很普遍,也许那时候的js并不太重要,只是用来做做验证或一些花哨的

  • 学习JavaScript事件流和事件处理程序

    本文全篇介绍了JavaScript事件流和事件处理程序,分享给大家供大家参考,具体内容如下 一.事件流 事件流描述的是从页面中接收事件的顺序.IE的事件流是事件冒泡流,而Netscape Communicator的事件流是事件捕获流. 二.事件冒泡 即事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点.如: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT

  • 详解JavaScript中的事件流和事件处理程序

    事件流:分两种,IE的是 事件冒泡流 ,事件开始时从最具体的元素接收,逐级向上传播到较为不具体的节点(Element -> Document).与之相反的是 Netscape 的 事件捕获流 . DOM2级事件规定事件流包括三个阶段:事件捕获阶段.处于目标阶段和事件冒泡阶段. 大多数情况下都是将事件处理程序添加到事件流的冒泡阶段.一个 EventUtil 的栗子: var EventUtil = { addHandler: function(element, type, handler){ if

  • JavaScript事件学习小结(一)事件流

    相关阅读: JavaScript事件学习小结(五)js中事件类型之鼠标事件 http://www.jb51.net/article/86259.htm JavaScript事件学习小结(一)事件流 http://www.jb51.net/article/86261.htm javaScript事件学习小结(四)event的公共成员(属性和方法) http://www.jb51.net/article/86262.htm JavaScript事件学习小结(二)js事件处理程序 http://www

  • 详解JavaScript 事件流

    事件 HTML中与javascript交互是通过事件驱动来实现的,例如鼠标点击事件.页面的滚动事件onscroll等等,可以向文档或者文档中的元素添加事件侦听器来预订事件.想要知道这些事件是在什么时候进行调用的,就需要了解一下"事件流"的概念. 事件流 事件流描述的就是从页面中接收事件的顺序.而早期的IE和Netscape提出了完全相反的事件流概念,IE事件流是事件冒泡,而Netscape的事件流就是事件捕获. 事件流类别 事件冒泡 即从下至上,从目标触发的元素逐级向上传播,直到win

  • 带你彻底搞懂JavaScript的事件流

    目录 DOM事件流 事件冒泡 事件捕获 情景一:直接在HTML中绑定事件 情景二:[domNode].onclick()方式——DOM0级 情景三:[domNode].addEventListener()方式——DOM2级 总结 DOM事件流 要明白事件流,首先我们要明白三点: 元素不是独立的,是串联在一起的 单个元素触发事件以后还会影响其他元素 事件流的方式:事件捕获(网景提出).事件冒泡(IE提出) 我们就以上图为例,假设你给div绑定了点击事件,当你点击了div后,其他元素也会受之牵连,会

  • 一起来学习一下JavaScript的事件流

    目录 1. 什么是事件流 ? 2. 事件流模型 2.1) 事件冒泡 2.2) 事件捕获 3. DOM 事件流 总结 1. 什么是事件流 ? 在学习事件流之前我们先看看什么是事件 ? 事件代表文档或浏览器窗口中某个有意义的时刻 即用户与页面的交互动作 (如用户点击元素时,鼠标移动到某个元素上等等) 事件的作用 JavaScript 与 HTML 的交互就是通过事件实现的 那么事件流是什么呢 ? 页面接受事件的顺序 2. 事件流模型 2.1) 事件冒泡 事件被定义为从最具体的元素(DOM 树的叶子)

  • JavaScript的事件流你了解吗

    目录 1. 什么是事件流 ? 2. 事件流模型 2.1) 事件冒泡 2.2) 事件捕获 3. DOM 事件流 总结 1. 什么是事件流 ? 在学习事件流之前我们先看看什么是事件 ? 事件代表文档或浏览器窗口中某个有意义的时刻 即用户与页面的交互动作(如用户点击元素时,鼠标移动到某个元素上等等) 事件的作用 JavaScript 与 HTML 的交互就是通过事件实现的 那么事件流是什么呢 ? 页面接受事件的顺序 2. 事件流模型 2.1) 事件冒泡 事件被定义为从最具体的元素(DOM 树的叶子)开

  • js事件流、事件委托与事件阶段实例详解

    目录 前言 1.事件流 2.事件处理程序 3.事件对象 4.跨浏览器事件处理 5.事件委托 总结 前言 JavaScript 与 HTML 的交互是通过事件实现的,事件代表文档或浏览器窗口中某个有意义的时刻.可以使用仅在事件发生时执行的监听器(也叫处理程序)订阅事件.本文总结一下 JS 中的事件相关知识点. 1.事件流 HTML 中与 javascript 交互是通过事件驱动来实现的,例如鼠标点击事件 onclick.页面的滚动事件 onscroll 等等,可以向文档或者文档中的元素添加事件侦听

随机推荐