前言
当用户在页面操作时,HTML DOM 允许 JavaScript 对 HTML 事件作出反应,可以根据对 HTML 的操作绑定相对应的事件,在事件中做出对应的处理。
HTML 事件的例子:
- 页面加载时
- 图片加载、加载完成、加载失败
- 用户点击页面
- 鼠标进入元素、移动到元素上、离开元素
- 敲击键盘 ...
DOM 事件的级别
DOM事件的级别包括 DOM0、DOM2、DOM3(没有 DOM1),其中 DOM2 和 DOM3 的区别是,DOM3 在 DOM2 的基础上新增很多事件类型,例如 鼠标事件、键盘事件 等
- DOM0:element.onclick = function() {}
- DOM2:element.addEventLister('click', function() {}, useCapture)
- DOM3:element.addEventLister('keyup', function() {}, useCapture) useCapture 可选。布尔值,指定事件是否在捕获或冒泡阶段执行
onClick 和 addEventLister 的区别:
- onClick 容易被重写覆盖,安全性低
- addEventLister上可以添加多个事件,而 onClick 只能添加一个事件,后面添加的事件会覆盖前面添加的事件
DOM 事件模型
DOM 的事件模型有两种,一种是捕获、一种是冒泡
- 事件的捕获:是由顶级元素一直向当前元素进行收缩,由外到内。注意:中间有事件的话执行顺序也是由外到内。
- 事件的冒泡:是由当前元素一直到顶级父级元素扩散,由内往外。注意:中间有事件的话执行顺序也是由内往外。
1、事件的捕获
<div id="ev">
<style>
#ev {
width: 300px;
height: 100px;
background: red;
color: #fff;
text-align: center;
line-height: 100px;
}
</style>
目标元素
</div>
<script>
// 冒泡方式
let pEv = document.getElementById('ev');
// window 的冒泡
window.addEventListener('click', function() {
console.log('冒泡阶段 window click')
}, false)
// document 的冒泡
document.addEventListener('click', function() {
console.log('冒泡阶段 document click')
}, false)
// html 的冒泡
document.documentElement.addEventListener('click', function() {
console.log('冒泡阶段 html click')
}, false)
// body 的冒泡
document.body.addEventListener('click', function() {
console.log('冒泡阶段 body click')
}, false)
// ev 节点的冒泡
pEv.addEventListener('click', function() {
console.log('冒泡阶段 pEv click')
}, false)
</script>
输出:
window click
document click
html click
body click
pEv click
2、事件的冒泡
<div id="ev">
<style>
#ev {
width: 300px;
height: 100px;
background: red;
color: #fff;
text-align: center;
line-height: 100px;
}
</style>
目标元素
</div>
<script>
// 捕获方式
let pEv = document.getElementById('ev');
// window 的冒泡
window.addEventListener('click', function() {
console.log('window click')
}, false)
// document 的冒泡
document.addEventListener('click', function() {
console.log('document click')
}, false)
// html 的冒泡
document.documentElement.addEventListener('click', function() {
console.log('html click')
}, false)
// body 的冒泡
document.body.addEventListener('click', function() {
console.log('body click')
}, false)
// ev 节点的冒泡
pEv.addEventListener('click', function() {
console.log('pEv click')
}, false)
</script>
输入
pEv click
body click
html click
document click
window click
DOM 事件流
用户触发了页面的一个事件造成事件流,流程:事件流 —— 事件捕获 —— 目标阶段 —— 事件冒泡 —— 上传到 window 对象
描述 DOM 事件捕获的具体流程
1、捕获流程
window —— document —— html —— body —— 目标元素的父级元素(没有就是到目标元素)—— 目标元素
2、冒泡流程(与捕获流程相反)
目标元素 —— 目标元素的父级元素(没有就是到目标元素)—— body —— html —— document —— window
Event 对象的常见应用
1、event.preventDefault()
阻止默认事件,例如 a 标签的 href 链接跳转
2、event.stopPropagation()
阻止冒泡行为
3、event.stopImmediatePropagation()
在目标元素上使用 addEventListener 或者其他方式绑定两个函数 fn1、fn2,按照先绑定先触发的原理,fn1 先触发,然后再执行 fn2,但是现在想触发 fn1 后不再执行 fn2,就在 fn1 上面执行一下 event.stopImmediatePropagation(),阻止 fn2 的执行。
let pDom = document.getElementById('demo');
pDom.addEventListener('click', fn1, false)
pDom.addEventListener('click', fn3, false)
function fn1(e) {
console.log('fn1', e.target)
fn2(e)
}
function fn2(e) {
console.log('fn2', e.target)
e.stopImmediatePropagation()
}
function fn3(e) {
console.log('fn3', e.target)
}
4、event.currentTarget
currentTarget 事件属性返回其监听器触发事件的节点,即当前处理该事件的元素、文档或窗口
5、event.target
一般使用在事件委托(事件代理)上面
事件委托:一般是一个父元素下面有多个子元素,并且要为它下面所有的子元素设置事件,可以用事件委托的方式,只绑定父元素事件,通过获取 target 去获取当前点击的元素
6、event.currentTarget 和 event.target 区别
在使用事件委托的事件,可以使用 event.currentTarget 获取绑定事件的元素,使用event.target 获取当前点击的元素
自定义事件(自动化测试时可以使用)
1、初始化一个事件 let evet = new Event(事件名)
2、定义一个事件 DOM.addEventListener(事件名, function() {}, false)
3、调用事件 DOM.dispatchEvent(evet)
4、CustomEvent 也可以自定义事件,它与 Event 不同的是,CustomEvent 可以带参数
// Event 自定义事件,不可以传参
let pDom = document.getElementById('demo');
let eve = new Event('custome');
pDom.addEventListener('custome', function(e) {
console.log('custome', e.target)
}, false)
pDom.dispatchEvent(eve)
// CustomEvent 自定义事件,可以传参
let pDom = document.getElementById('demo');
const eve = new CustomEvent('custome', {
detail: {
message: 'Hello World',
time: new Date(),
}
} );
pDom.addEventListener('custome', function(e) {
console.log(e)
}, false)
pDom.dispatchEvent(eve)