什么是事件处理程序?
事件就是用户或浏览器自身执行的某种动作。如click、mousemove、load,都是事件的名字。而响应某个事件的函数就叫做事件处理程序(或事件侦听器)。事件处理程序的名字都是以'on'开头,因此click事件的事件处理程序就是onclick,load事件的事件处理程序就是onload。为事件指定处理程序的方式有多种。
HTML事件处理程序
某个元素支持的每种事件,都可以使用一个与相应的事件处理程序同名的HTML特性来指定。这个特性的值应该是能够执行的JavaScript代码。
// 这里只做简单的简介,如果需要深入的了解关于动态创建的函数,扩展作用域的方式。自行查资料(红宝书三版 p349)
<input type='button' value='onclick me' onclick='alertMessage()'>
<script type='text/javascript'>
function alertMessage() {
alert('click me')
}
</script>
在html中指定事件处理程序的缺点
1、时差问题,因为用户可能会在html元素一出现在页面上就触发相应的事件,但是当时的时间处理程序可能不具备执行条件。以上面的例子来说,假设alertMessage()函数是在按钮下方、页面最底部定义的。如果用户在页面解析alertMessage()之前点击了按钮,就会引发错误。为此,在定义这个处理程序的时候可以增加一个try - catch判断。
<input type='button' value='onclick me' onclick='try{alertMessage()}catch(e) {} '>
<script type='text/javascript'>
function alertMessage() {
alert('click me')
}
</script>
<!--这里就只介绍一种,如果有兴趣知道更多,可以查一下资料-->
DOM0级事件处理程序
将一个函数赋值给一个事件处理程序属性。目前所有现代浏览器都支持,原因一简单,二是具有跨浏览器的优势
// 在下面这些代码运行之前,不会指定对应的事件处理程序,可能点击按钮没有触发alert()方法
let btn = documnet.getElementById('btn');
btn.onclick = function() {
alert('click me')
//this此时执行这个元素的引用
}
// 也可以删除指定的方法
btn.onclick = null
DOM2级事件处理程序
addEventListener()和removeEventListener()。所有的dom节点中都包含这两个方法,它们接收三个参数:要处理的事件名称、事件处理函数和一个布尔值。这个布尔值代表true - 捕获阶段调用事件处理程序;false - 冒泡阶段调用
let btn = documnet.getElementById('btn');
// 为什么不采用匿名函数写法,移除方法需要传入的参数和添加的时候相等
function handler(){
// 与DOM0级事件处理程序一样,这里添加的事件处理程序也是在其依附的元素的作用域
alert('click', this.id)
}
btn.addEventListener('click', handler, false);
// 参数需要相等
btn.removeEventListener('click', handler, false);
采用DOM2级事件处理程序有什么好处
采用DOM2级处理程序可以添加多个事件处理程序。并且是按照顺序触发,从上往下
let btn = documnet.getElementById('btn');
function handler1(){
alert('click1', this.id)
}
function handler2(){
alert('click2', this.id)
}
btn.addEventListener('click', handler1, false);
btn.addEventListener('click', handler2, false);
IE事件处理程序
attachEvent()和detachEvent();接收相同的两个参数:事件处理名称,事件处理函数;由于IE9之前只支持事件冒泡,所以通过attachEvent()添加的事件处理程序都会被添加到冒泡阶段
let btn = documnet.getElementById('btn');
function handler(){
alert('click', this.id)
}
// !!!注意这里是onclick不是click
btn.attachEvent('onclick', handler)
// 移除方法
btn.detachEvent('onclick', handler)
// attachEvent()与使用DOM0级方法的主要区别在于事件处理程序的作用域。IE中指向window
btn.attachEvent('onclick', function() {alert(this == window)}) // true
采用IE级事件处理程序有与DOM2级事件处理程序有什么区别
采用IE处理程序添加的多个事件处理程序。并且是以相反的方向触发触发,从下往上
let btn = documnet.getElementById('btn');
function handler1(){
alert('click1', this.id)
}
function handler2(){
alert('click2', this.id)
}
btn.attachEvent('onclick', handler1);
btn.attachEvent('onclick', handler2);
// click2 ---> click1
一个通用的跨浏览器的事件处理程序
仅供参考
const EventUtils = {
// 视能力分别使用 dom0 || dom2 || IE 方式,来绑定事件
// 添加事件
addEvent: 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;
}
},
// 移除事件
removeEvent: 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;
}
}
// 获取事件目标
getTarget: function(event) {
return event.target || event.srcElement;
},
// 获取 event 对象的引用,取到事件的所有信息,确保随时能使用 event
getEvent: function(event) {
return event || window.event;
},
// 阻止事件(主要是事件冒泡,因为 IE 不支持事件捕获)
stopPropagation: function(event) {
if (event.stopPropagation) {
event.stopPropagation();
}else {
event.cancelBubble = true;
}
}
// 取消事件的默认行为
preventDefault: function(event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
}
}