事件的捕获和冒泡机制
捕获过程:window->document->body->div->text
冒泡过程:text->div->body->document->window
addEventListener
addEventListener方法用来为一个特定的元素绑定一个事件处理函数,共有三个参数:
element.addEventListener(event, function, useCapture)
event
必填项,字符串类型,表示绑定的是哪种事件(注意把所有的on去掉,比如onclick,改为click,其它同理),绑定类型参考 绑定事件参考手册。
function
可选填,事件处理函数,事件对象会作为第一个参数传入函数。事件对象的类型取决于特定的事件。比如click事件属于MouseEvent(鼠标事件)对象
useCapture
Boolean类型,true或false(默认为false)。
true表示事件在捕获阶段执行。
false表示事件在冒泡阶段执行。
什么是事件冒泡
假如有一层嵌套的div,每一层div上都添加了点击事件,事件会从最里面往外触发,这就是事件冒泡。
如下面的代码:outer->middle->inner->button
,所有元素添加的都是冒泡事件,useCapture为false
当点击button时,事件触发会从里往外冒,依次打印bubble button->bubble inner->bubble middle->bubble outer
同理点击inner时,依次打印bubble inner->bubble middle->bubble outer
点击middle时,依次打印bubble middle->bubble outer
点击outer时,打印bubble outer
<style>
div {
padding: 30px;
}
.outer {
background-color: pink;
}
.middle {
background-color: green;
}
.inner {
background-color: orange;
}
</style>
<body>
<div class="outer">
<div class="middle">
<div class="inner">
<button>click me</button>
</div>
</div>
</div>
<script type="module">
const $ = (selector)=>{
return document.querySelector(selector)
}
// 冒泡
$('.outer').addEventListener('click',function(e){
console.log('bubble outer');
}, false)
$('.middle').addEventListener('click',function(e){
console.log('bubble middle');
}, false)
$('.inner').addEventListener('click',function(e){
console.log('bubble inner');
}, false)
$('button').addEventListener('click',function(e){
console.log('bubble button');
}, false)
</script>
</body>
什么是事件捕获
假如有一层嵌套的div,每一层div上都添加了点击事件,事件会从最外面往里触发,这就是事件捕获。
如下面的代码:outer->middle->inner->button
,所有元素添加的都是捕获事件,useCapture为true
当点击outer时,事件触发会从外往里触发,依次打印capture outer->capture middle->capture inner->capture button
同理点击middle时,依次打印capture middle->capture inner->capture button
点击inner时,依次打印capture inner->capture button
点击button时,打印``capture button`
<style>
div {
padding: 30px;
}
.outer {
background-color: pink;
}
.middle {
background-color: green;
}
.inner {
background-color: orange;
}
</style>
<div class="outer">
<div class="middle">
<div class="inner">
<button>click me</button>
</div>
</div>
</div>
<script type="module">
const $ = (selector)=>{
return document.querySelector(selector)
}
// 捕获
$('.outer').addEventListener('click',function(e){
console.log('capture outer');
}, true)
$('.middle').addEventListener('click',function(e){
console.log('capture middle');
}, true)
$('.inner').addEventListener('click',function(e){
console.log('capture inner');
}, true)
$('button').addEventListener('click',function(e){
console.log('capture button');
}, true)
</script>
</body>
同时都存在时,先触发哪一个
先触发捕获,后触发冒泡
e.target
和e.currentTarget
的区别
e.target
:是自己实际点击的那个div
e.currentTarget
:是绑定事件函数后,因捕获或者冒泡机制而触发的那个div
所以有个很巧妙的判断,e.target===e.currentTarget
,表示是自嗨型,自己的事件,点击的自己,触发也是自己的事件函数。当不相等时,说明事件是通过冒泡或者捕获触发的。
阻止事件冒泡
e.stopPropagation()
阻止默认行为
e.preventDefault()
事件委托
假如ul里有100个li,每个li都需要绑定点击事件,常规做法是遍历每个li,然后绑定点击事件。
这种做法在li非常少的情况下还行,当有非常多的li时,就不可取了。
所以这时可以将事件绑定到父级ul身上,根据事件冒泡机制,点击li时,仍然可以将点击事件冒泡给ul,触发父级ul的点击事件。然后通过e.target找到实际点击的元素,就可以判断出来是哪一个li。
常见事件
鼠标事件
click
:用户点击元素。dblclick
:用户双击元素。mousedown
:用户按下鼠标按钮。mouseup
:用户释放鼠标按钮。mousemove
:鼠标在元素上移动。mouseenter
:鼠标进入元素边界。mouseleave
:鼠标离开元素边界。mouseover
:鼠标移入元素或其子元素。mouseout
:鼠标移出元素或其子元素。contextmenu
:用户触发上下文菜单(通常是通过鼠标右键)。
键盘事件
keydown
:用户按下键盘上的键。keyup
:用户释放键盘上的键。keypress
:用户按下键盘上的键(已废弃,不建议使用)。
焦点事件
focus
:元素获得焦点。blur
:元素失去焦点。focusin
:元素即将获得焦点。focusout
:元素即将失去焦点。
表单事件
change
:元素的值发生变化。input
:用户输入数据时触发。submit
:表单提交。reset
:表单重置。
触摸事件
touchstart
:用户触摸屏幕。touchmove
:用户手指在屏幕上移动。touchend
:用户手指从屏幕上抬起。touchcancel
:触摸被中断。
UI事件
resize
:窗口或框架被调整大小。scroll
:元素滚动。
进度事件
load
:对象加载完成。unload
:对象正在被卸载。beforeunload
:即将卸载页面。error
:在加载文档或图像时发生错误。abort
:对象加载被中止。
资源事件
loadstart
:开始加载。progress
:加载过程中。loadend
:加载结束。
动画和过渡事件
animationstart
:CSS动画开始。animationend
:CSS动画结束。animationiteration
:CSS动画重复。transitionend
:CSS过渡完成。
其他事件
drag
:元素被拖动。drop
:拖放操作结束。select
:用户选择文本。wheel
:鼠标滚轮在元素上滚动。