事件
事件是什么
所谓事件,就是浏览器告知 JavaScript 程序用户的行为。例如用户点击了 HTML 页面中的某个按钮,或者用户输入用户名或密码等操作。
如下示例代码,演示了如何通过事件完成用户点击按钮后的逻辑:
<div class="button-group">
<button id="btn" class="button">按钮</button>
</div>
<script>
// 获取按钮元素
var btn = document.getElementById('btn');
// 事件绑定
btn.onclik = function(){
console.log('你终于点中我了...');
}
</script>
事件类型
事件根据场景不同,可以分为如下几种:
- 依赖于设备的输入事件:键盘事件和鼠标事件,这些事件都是直接和设备相关的。
- 独立于设备的输入事件:例如click事件等,这些事件并没有直接与设备相关。
- 用户界面的相关事件:用户界面事件属于较高级的事件,一般多用于表单中的组件。
- 状态变化的相关事件:这些事件与用户行为无关,而是由网络或浏览器触发的。
- 特定 API 事件:这些事件多用于特定场景的实现,例如 HTML5 中提供的拖放 API 中的事件等。
- 与错误处理的相关事件。
事件的实现的步骤
如事件部分示例的代码所示:
- 定位页面中指定的元素
var btn = document.getElementById('btn');
- 为指定元素绑定事件 - 具有一个事件监听器(监听用户的相应行为)
btn.onclik = function(){
// console.log('你终于点中我了...');
}
- 为绑定的事件编写相应的处理函数(用户触发相应的行为时,函数做出响应)
console.log('你终于点中我了...'); // 函数体
注册事件是什么
所谓注册事件,就是将 JavaScript 函数与指定的事件相关联,被绑定的函数称为该事件的句柄。该事件被触发时,绑定的函数会被调用。
注册事件具有以下三种方式实现:
- HTML 页面元素提供的事件属性
- DOM 标准规范中 HTML 相关对象提供的事件属性
- 通过向 HTML 页面中指定元素添加事件监听器
如图所示:
DOM 对象的事件属性
通过 DOM 标准规范中的 Document 对象定位 HTML 页面的元素,所返回的 DOM 对象提供了一系列的事件属性,通过这些事件属性可以实现注册事件的功能。
<div class="button-group">
<button id="btn" class="button">按钮</button>
</div>
<script>
var btn = document.getElementById('btn');
btn.onclik = myClick;
function myClick() {
console.log('你终于点中我了...');
}
</script>
通过 DOM 对象的事件属性方式注册事件,是不允许重复注册的。如果以这种方式为某个元素注册相同事件多次的话,只有最后一次注册的函数有效。
事件监听器
DOM 标准规范提供的 addEventListener() 方法,调用该方法表示向指定元素添加事件监听器。
element.addEventListener(eventName,functionName.capture)
参数名称 | 描述 |
---|---|
eventName | 为元素指定具体的事件名称(例如单击事件是 click 等) |
functionName | 注册事件的句柄 |
capture | 设置事件是捕获阶段还是冒泡阶段。false 为默认值,表示冒泡阶段 |
<div class="button-group">
<button id="btn" class="button">按钮</button>
</div>
<script>
var btn = document.getElementById('btn');
btn.onclik = function(){
console.log('你终于点中我了...');
}
</script>
为指定元素添加事件监听器:addEventListener(eventName,callback)
参数:
- eventName - 表示绑定的事件名称(注意:没有 on)
- callback - 表示事件的处理函数(回调函数)
DOM 对象提供的事件属性,无法同时为一个指定元素绑定相同事件多次
btn.onclick = function() {
console.log('test');
}
btn.onclick = function() {
console.log('test2');
}
但是 DOM 允许相同元素绑定相同事件多次
btn.addEventListener('click',function(){
comsole.log('test3');
});
btn.addEventListener('click',function(){
comsole.log('test4');
});
事件监听器在浏览器中存在兼容问题(IE8 以下浏览器版本不支持)
可以利用attachEvent(eventName,functionName) 方法
- eventName 表示事件名称(注意:必须有 on )
- functionName 表示事件的处理函数
用法示例:
btn.attachEvent('onclik',function(){
console.log('text5');
});
浏览器兼容解决方案:
function bind(element,eventName,functionName){
if (element.addEventListener){
element.addEventListener(eventName,functionName);
} else {
element.attachEvent('on' + eventName,functionName);
};
};
事件监听器中的 this
当使用 addEventListener()
方法为某个HTML页面元素注册事件的时候,this 就指代注册事件的元素。
btn.addEventListener('click',function(){
console.log(this.text.Content);
})
当使用 attachEvent()
方法为某个 HTML 页面元素注册事件的时候,this 指代的是 window 对象,而不是注册事件的元素。
var btn = document.getElementById('btn');
btn.addachEvent('onclick',function(){
console.log(this); // 输出 [Object window]
})
由于 addEventListener()
方法中的 this 与 attachEvent()
方法中的 this 的含义不同,我们需要将监听器的浏览器兼容方案进行优化:
function bind(elem,event,callbcak){
// 判断是否存在 addEventListener
if (elem.addEventListener){
elem.addEventListener(event,callback,false);
} else {
elem.attachEvent('on' + event,function(){
// 将 this 的指向修改为注册事件的元素
callback.call(elem);
});
};
};
移除注册事件
DOM 标准规范提供的 removeEventListener() 方法,调用该方法表示向指定元素移除事件监听器。
elentName.removeEventListener(eventName,functionName,capture)
参数名称 | 描述 |
---|---|
eventName | 表示移除的事件名称(例如单击事件是 click 等) |
functionName | 注册事件的句柄(之前使用 addEventListener() 方法定义的) |
capture | 设置事件是捕获阶段还是冒泡阶段。false 为默认值,表示冒泡阶段 |
var btn = document.getElementById('btn');
function listener(){
console.log('你终于点中了我');
}
btn.addEventListener('click',listener);
btn.removeEventListener('click',listener);
detachEvent() 方法
移除事件在 IE8 及之前版本的浏览器都不支持 removeEventListener() 方法,而是单独提供了 detachEvent 方法。
element.detachEvent(eventName,functionName)
参数名称 | 描述 |
---|---|
eventName | 表示移除的事件名称(例如单击事件是 click 等) |
functionName | 注册事件的句柄(之前使用 addEventListener() 方法定义的) |
var btn = document.getElementById('btn');
function listener(){
console.log('你终于点中了我');
}
btn.attachEvent('click',listener);
btn.detachEvent('click',listener);
浏览器兼容
与注册事件相似,移除注册事件在实际开发中,同样需要兼容各大浏览器,具体解决方案如下:
function unbind(element,eventName,functionName) {
if (element.removeEventListener){
element.removeEventListener(eventName,functionName);
} else {
element.detachEvent('on' + eventName,functionName);
}
}
事件对象是什么
为 HTML 页面中的元素注册事件时,事件的处理函数具体一个 参数,该参数就是 Event 事件对象。 Event 事件对象中包含了该事件的信息,以及该事件发生在哪个元素上。
element.addEventListener(eventName,function(event){
// event 就是事件对象
},capture)
注意:
- 当事件发生时,Event 事件对象会被创建井依次传递给事件监听器。
- 由于 Event 事件对象是事件处理函数的参数,所以参数名允许自定义的。
事件对象:事件的处理函数中接收一个参数。
Event 事件对象作为所有事件对象的父级
- MouseEvent 事件对象 - 表示鼠标事件
- KeyboardEvent 事件对象 - 表示键盘事件
- TouchEvent 事件对象 - 表示触摸事件
<script>
var btn = document.getElementById('btn');
// 事件的处理函数中接收一个参数 - 事件对象
btn.addEventListener('click',function(event){
console.log(event);
})
</script>
浏览器兼容
IE8 及之前版本的浏览器,HTML 页面元素注册事件时,Event 事件对象并不是作为事件的处理函数的参数,而是作为 window 对象的属性存在的。
<div class="button-group">
<button id="btn" class="button">按钮</button>
</div>
<script>
var btn = document.getElementById('btn');
btn.attachEvent('onclick',function(){
console.log(window.event);
})
</script>
事件对象的 button 属性
鼠标右键功能案例
<script>
// document对象和<html>标签绑定鼠标点击事件有效
var html = document.documentElement;
var body = document.body;
html.addEventListener('mousedown',function(event){
if(event.button === 2 ){
//提供一个自定义菜单
}
});
</script>
- click事件 - 表示鼠标点击事件(鼠标左键)
- mousedown事件 - 表示鼠标事件被按下事件
- mouseup事件 - 表示鼠标按键被释放事件
- event事件对象提供了button属性:用于表示鼠标按键
- 0 = 表示鼠标左键
- 1 - 表示鼠标滚轮
- 2 - 表示鼠标右键
获取目标元素
结构代码:
<ul id="phone">
<li>苹果</li>
<li id="smartisan"><a href="#">锤子</a></li>
<li>小米</li>
</ul>
tarfet 属性
Event 事件对象提供了 target 属性,用于获取触发当前事件的 HTML 元素。
phone.addEventListener('click',function(event){
// target属性 - 获取触发当前事件的目标元素
console.log(event.target);
});
tarfet 属性的浏览器兼容问题
IE8 及之前版本浏览器并不支持 target 属性,而是提供了与 target 属性作用相同的 srcElement 属性。
var phone = document.getElementById('phone');
phone.addEventListener('onclick',function(event){
event = event || window.event;
console.log(event.srcElement);
});
currentTarget 属性与 this
事件处理函数中的 this ,作用与事件对象的 currentTarget 属性相同,可以获取注册当前事件的 HTML 元素。
phone.addEventListener('click',function(event){
// currentTarget属性 - 获取绑定当前事件的目标元素
console.log(event.currentTarget);
// this等同于currentTarget属性 - 获取绑定当前事件的目标元素
console.log(this);
});