JavaScript和HTML之间的交互是通过事件实现的。事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间。点击按钮这件事,就被称作事件,而响应某个事件的函数通常被称为事件处理程序
1.接下来先说下DOM事件
DOM事件级别
DOM有4次版本更新,与DOM版本变更,产生了3种不同的DOM事件:DOM 0级事件处理,DOM 2级事件处理和DOM 3级事件处理。由于DOM 1级中没有事件的相关内容,所以没有DOM 1级事件。
DOM 0级事件
1.on-event (HTML 属性):
<button onclick="alert('xxx')">Click</button>
on-event (非HTML 属性):
像是window或document此类没有实体元素的情况:
window.onload = function(){
document.write("Hello world!");
};
若是实体元素:
<button id="btn">Click</button>
var btn = document.getElementById('btn');
btn.onclick = function(){
alert(this.id);//这个this 指向当前元素
}
解除绑定
btn.onclick = null
2.同一个元素的同一种事件只能绑定一个函数,否则后面的函数会覆盖之前的函数
3.不存在兼容性问题
DOM 2级事件
1.Dom 2级事件是通过 addEventListener 绑定的事件
2.同一个元素的同种事件可以绑定多个函数,按照绑定顺序执行
3.解绑Dom 2级事件时,使用 removeEventListener
btn.addEventListener("click", function () {
console.log("btn")
}, false);
btn.addEventListener("click", function () {
console.log("btn1");
}, false);
解绑
btn.removeEventListener( "click" ,函数名,事件流阶段)
Dom 2级事件有三个参数:第一个参数是事件名(如click);第二个参数是事件处理程序函数;第三个参数如果是true的话表示在捕获阶段调用,为false的话表示在冒泡阶段调用
注意:
1.removeEventListener():不能移除匿名添加的函数。
2.IE9之下的浏览器不支持DOM2级事件处理程序
IE事件处理程序
IE9之前的浏览器实现了DOM中类似的两个方法 attachEvent和detachEvent。由于IE9之前的版本只支持事件冒泡,所以它只有两个参数
1.同一个元素的同种事件可以绑定多个函数,但是执行顺序不是按照添加他们的顺序执行,而是相反的顺序触发
2.解绑事件时,使用 detachEvent
btn.attachEvent("onclick", function () {
//console.log(this===window);//这个this指向window的
console.log("btn")
})
btn.attachEvent("onclick", function () {
console.log("btn1")
})
执行结果是 btn1,btn
解绑
btn.detachEvent( "onclick" ,函数名)
DOM 3级事件
- UI事件,当用户与页面上的元素交互时触发,如:load、scroll 焦点事件,当元素获得或失去焦点时触发,如:blur、focus
- 鼠标事件,当用户通过鼠标在页面执行操作时触发如:dblclick、mouseup
- 滚轮事件,当使用鼠标滚轮或类似设备时触发,如:mousewheel 文本事件,当在文档中输入文本时触发,如:textInput
- 键盘事件,当用户通过键盘在页面上执行操作时触发,如:keydown、keypress
- 合成事件,当为IME(输入法编辑器)输入字符时触发,如:compositionstart
- 变动事件,当底层DOM结构发生变化时触发,如:DOMsubtreeModified 同时DOM3级事件也允许使用者自定义一些事件。
DOM事件流
事件流指的就是网页元素接收事件的顺序。事件流可以分成两种机制:
-
事件捕获(Event Capturing)(会从document开始触发,一级一级往下传递,依次触发,直到真正事件目标为止)
- -
事件冒泡(Event Bubbling)(从当前触发的事件目标一级一级往上传递,依次触发,直到document为止)
-
当一个事件发生后,会在子元素和父元素之间传播(propagation)。这种传播分成三个阶段:
1.捕获阶段:事件从window对象自上而下向目标节点传播的阶段;
2.目标阶段:真正的目标节点正在处理事件的阶段;
3.冒泡阶段:事件从目标节点自下而上向window对象传播的阶段
注意:
1.尽管“DOM2级事件”规范要求事件应该从document对象开始传播,但是IE9,Safari,Chrome,Opera和Firefox这些浏览器都是从window对象开始捕获事件的
2.IE8以及更早版本的浏览器不支持捕获阶段,而且只冒泡到document
我们可以通过addEventListener()方法来绑定click事件:
假设HTML 如下:
<div class="parent">
<div class="child"></div>
</div>
JavaScript 代码如下:
var parent = document.querySelector(".parent");
var child = document.querySelector(".child");
parent.addEventListener("click", function () {
console.log("捕获:parent");
}, true);
parent.addEventListener("click", function () {
console.log("冒泡:parent");
}, false);
child.addEventListener("click", function () {
console.log("捕获:child");
}, true);
child.addEventListener("click", function () {
console.log("冒泡:child");
}, false);
捕获:parent
捕获:child
冒泡:child
冒泡:parent
而如果直接点击「父元素」,则出现:
捕获:parent
冒泡:parent
那么,子层中的捕获或冒泡谁先谁后呢?要看你代码的顺序而定:谁在前就先执行谁