事件的捕获和冒泡机制
捕获过程: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:鼠标滚轮在元素上滚动。