JavaScript权威指南(个人笔记):(十)事件处理
事件类型(event type)是一个用来说明发生什么类型事件的字符串。例如,“keydown”表示键盘上某个键被按下。由于事件类型只是一个字符串,因此实际上有时会称为事件名字(event name)
事件目标(event target)是发生的事件或与之相关的对象。当讲事件时,我们必须同时指明类型和目标,例如,window上的load事件或<button>元素的click事件。
事件处理程序(event handler)或事件监听程序(event listener)是处理或相应事件的函数,应用程序通过指明事件和事件目标,在Web浏览器中注册他们的事件处理程序函数。应用程序通过指明事件类型和事件目标,在Web浏览器中注册他们的事件处理程序函数。当特定的目标上发生特定类型的事件时,浏览器会调用对应的处理程序。当对象上注册的事件处理程序被调用时,我们有时会说浏览器“触发”(fire,trigger)和“派发”(dispatch)了事件。
事件对象(event object)是与特定事件相关且包含有关该事件详细信息的对象。事件对象作为参数传递给事件处理程序函数。所有的事件对象都有用来指定事件类型的type属性和指定事件目标的target属性
事件传播(event propagation)是浏览器决定哪个对象触发其事件处理程序的过程。当文档元素上发生某个类型的事件时,然而,他们会在文档树上向上传播或“冒泡”(bubble)。有时,在Document或其他容器元素上注册单个事件处理程序比在每个独立的目标元素上都注册处理程序要更方便。
事件传播的另外一种形式称为事件捕获(evnet capturing),在容器元素上注册的特定处理程序有机会在事件传播到真实目标之前拦截(或“捕获”)它。
一些事件有与之相关的默认操作。例如,例如,当超链接上发生click事件时,浏览器的默认操作是按照链接加载新页面。事件处理程序可以通过返回一个适当的值,调用事件对象的某个方法或设置事件对象的某个属性来阻止默认操作的发生。有时称为“取消”事件。
注册事件处理程序
三种方式:
1.设置JavaScript对象属性为事件处理程序
注册事件处理程序最简单的方式就是通过设置事件目标的属性为所需事件处理程序函数。
比如:
window.onload = function() { ... } // 设置window对象的onload属性为一个函数
事件处理程序属性的缺点是其设计都是围绕着假设每个事件目标对于每种事件类型将最多只有一个处理程序。
如果想编写能够在任意文档中都能使用的脚本库代码,更好的方式是使用一种不修改或覆盖任何已有注册处理程序的技术(比如addEventListener())
2.设置HTML标签属性为事件处理程序
用于设置的文档元素事件处理程序属性(property)也能换成对应HTML标签的属性(attribute)。
如果这样做,属性值应该是JavaScript代码字符串。这段代码应该是事件处理程序函数的主体,而非完整的函数声明。
也就是说,HTML事件处理程序代码不应该用大括号包围且使用function关键字作为前缀。例如:
<button onclick="alert('hello');">click here</button>
当指定一串JavaScript代码作为HTML事件处理程序属性的值时,浏览器会把代码串转换为类似如下的函数中:
function(event) {
with(document) {
with(this.form || {}) {
with(this) {
...
}
}
}
}
客户端编程的通用风格是保持HTML内容和JavaScript行为分离,遵循这条规则的程序员应禁止(或至少避免)使用HTML事件处理程序属性,因为这些属性直接混合了JavaScript和HTML。
3.addEventListener()
这个方法为事件目标注册事件处理程序。
有三个参数:
1.要注册的事件类型(名称)
2.当指定类型的事件发生时调用的函数
3.布尔值(捕获时用,有时可以忽略这个参数)
用“click”作为第一个参数调用addEventListener()不会影响onclick属性的值。
更重要的是,能通过多次调用addEventListener()为同一个对象注册同一事件类型的多个处理程序函数。
使用相同的参数在同一个对象上多次调用addEventListener()是没用的,处理程序仍然只注册一次。
相对的方法是removeEventListener() 删除事件处理程序(同样有三个参数)
事件处理程序的参数
通常调用事件处理程序时把事件对象作为他们的一个参数。事件对象的属性提供了有关事件的详细信息。 例如:type属性指定了发生的事件类型。
事件处理程序的运行环境
事件处理程序在事件目标上定义,所以他们作为这个对象的方法来调用并不出人意料。这就是说,在事件处理程序内,this关键字指的是事件目标。
甚至当使用addEventListener()注册时,调用的处理程序使用事件目标对象作为他们的this值
事件处理程序的返回值
通过设置对象属性或HTML属性注册事件处理程序的返回值有时是非常有意义的。通常情况下,返回值false就是告诉浏览器不要执行这个事件相关的默认操作。
例如,表单提交按钮的onclick事件处理程序能返回false阻止浏览器提交表单。(当用户的输入在客户端验证失败时,这是有用的)
理解事件处理程序的返回值只对通过属性注册的处理程序才有意义这非常重要。
使用addEventListener()注册事件处理程序转而必须调用preventDefault()方法或设置事件对象的returnValue属性
事件传播
调用在目标元素上注册的事件处理函数后,大部分事件会“冒泡”到DOM树根。
调用目标的父元素的事件处理程序,然后调用在目标的祖父元素上注册的事件处理程序。这会一直到Document对象,最后到达Window对象。
事件冒泡为在大量单独文档元素上注册处理程序提供了替代方案,即在共同的祖先元素上注册一个处理程序来处理所有的事件。
例如:可以在<form>元素上注册“change”事件处理程序来取代在表单的每个元素上注册“change”事件处理程序。
第一个阶段:发生在目标处理程序调用之前,称为“捕获”阶段
第二个阶段:目标对象本身调用事件处理程序
第三个阶段:事件冒泡
事件传播的捕获阶段像反向的冒泡阶段。
最先调用Window对象的捕获程序—>Document对象—>body对象—>DOM树—>以此类推,直到调用事件目标的父元素的捕获事件处理程序(在目标对象本身上注册的捕获事件处理程序不会被调用。)
事件捕获提供了在事件没有送达目标之前查看他们的机会。事件捕获能用于程序调试,或用于事件取消。
事件取消
event.preventDefault() 取消事件的默认操作。
event.stopPropagation() 阻止事件的继续传播。
如果在同一对象上定义了其他处理程序,剩下的处理程序将依旧被调用,但调用stopPropagation()之后任何其他对象上的事件处理程序将不会被调用。
stopPropagation()方法可以在任何阶段调用,他能工作在捕获阶段,事件目标本身中和冒泡阶段
浙公网安备 33010602011771号