一.事件流
事件流是对事件执行过程的描述,就是整个事件的流动过程。
任意事件被触发时总会经历两个阶段:【捕获阶段】和【冒泡阶段】。
简言之,捕获阶段是【从父到子】的传导过程,冒泡阶段是【从子向父】的传导过程
1.捕获和冒泡
a.如果事件是在捕获阶段执行的,我们称为捕获模式,它会先执行父盒子事件再去执行子盒子事件。 (从上到下)
b.如果事件是在冒泡阶段执行的,我们称为冒泡模式,它会先执行子盒子事件再去执行父盒子事件,默认是冒泡模式。 (从下到上)
DOM对象.addEventListener('点击事件',函数,true)
结论:
addEventListener
第3个参数决定了事件是在捕获阶段触发还是在冒泡阶段触发addEventListener
第3个参数为true
表示捕获阶段触发,false
表示冒泡阶段触发,默认值为false
- 事件流只会在父子元素具有相同事件类型时才会产生影响
- 绝大部分场景都采用默认的冒泡模式(其中一个原因是早期 IE 不支持捕获
2.阻止冒泡
a.概述
阻止冒泡是指阻断事件的流动,保证事件只在当前元素被执行,而不再去影响到其对应的祖先元
<body>
<div class="father">
<div class="son"></div>
</div>
<script>
const fa = document.querySelector('.father')
const son = document.querySelector('.son')
document.addEventListener('click', function () {
alert('爷爷')
})
fa.addEventListener('click', function () {
alert('爸爸') //点击father div会冒泡到document上的点击事件
})
son.addEventListener('click', function (e) {
alert('儿子')
// 组织流动传播 事件对象.stopPropagation()7
e.stopPropagation()
})
</script>
</body>
b.注意
鼠标经过事件:
mouseover 和 mouseout 会有冒泡效果
mouseenter 和 mouseleave 没有冒泡效果 (推荐)
<body>
<div class="dad">
<div class="baby"></div>
</div>
<script>
const dad = document.querySelector('.dad')
const baby = document.querySelector('.baby')
dad.addEventListener('mouseover', function () {
console.log('鼠标经过')
})
dad.addEventListener('mouseout', function () {
console.log('鼠标离开')
})
</script>
</body>
现在解析一下这个不常用的mouseover和mouseout,我先从大div进去一直进到小div,再从里面出来到初始位置,控制台输出结果如下
鼠标进入小div会同时产生离开和经过,因为是在大div上绑定的点击事件,所有离开大div时会产生离开,但是接下来进入小div,你的鼠标也在移动,虽然它的身上并没有绑定相应鼠标事件,但是在它身上发生了鼠标移动,它还是会冒泡到大div上相同类型的事件,即为产生了鼠标经过的输出,下面的同理.
总结一下
1.如果父绑定了和子触发事件不同的事件处理函数,那子冒泡到父,父确实不会执行函数
2.但是事件确实是传递了,只是因为父没有绑定同名事件的对应函数,所以没有表现出来
3.不是说不绑定事件处理函数就不会冒泡,还是会冒泡的,参考上面的例子
二.事件委托
事件委托是利用事件流的特征解决一些现实开发需求的知识技巧,主要的作用是提升程序效率。 大量的事件监听是比较耗费性能的,它利用的就是冒泡,先将事件委托到父元素上,然后让子元素能够取到它,大大减少事件监听的总数。
不用事件委托绑定监听事件
使用事件委托绑定事件(根据就是很多相同的子元素都要绑定相同的事件,但是循环绑定会耗费性能,所以把事件绑定到父元素身上,等着子元素冒泡到父元素然后激发相应事件)
三.其它事件
1.页面加载事件
A. 加载外部资源(如图片、外联CSS和JavaScript等)加载完毕时触发的事件
有些时候需要等页面资源全部处理完了做一些事情
事件名:load
监听页面所有资源加载完毕:
window.addEventListener('load', function() { // xxxxx })
B. 当初始HTML文档被完全加载和解析完成之后,DOMContentLoaded事件被触发,无需等待样式表,图像等完全加载
事件名:DOMContentLoaded
document.addEventListener('DOMContentLoaded', function () {
})
2.元素滚动事件
滚动条在滚动的时候持续触发的事件
如果整个body的长度或宽度大于浏览器窗口显示的范围,就可以设置相应的元素滚动事件
window.addEventListener('scroll', function() { // xxxxx })
其中scrollTop属性是指已经滚动到的位置距离初始位置的距离,返回的是数字
<script>
const div = document.querySelector('div')
// div.addEventListener('scroll', function () {
// console.log(div.scrollTop); //控制台输出滚动距离
// })
window.addEventListener('scroll', function () {
const n = document.documentElement.scrollTop //指整个HTML界面距离界面最上方滚动的距离
if (n >= 100) {
div.style.display = 'block' //控制div的出现和消失
} else {
div.style.display = 'none'
}
})
</script>
像上面例子中的div如果文字溢出,可以直接加上滚动条效果,用css加入overflow: scroll;属性即可,如果想要加入滚动事件,再模仿上面的步骤就行
3.页面尺寸事件
a.会在窗口尺寸改变时触发事件
window.addEventListener('resize', function() { // xxxxx })
b.检测屏幕宽度
c.获取元素可见部分宽高(不含边框border,margin,滚动条等)
clientWidth和clientHeight
clientTop和clientLeft的大小就是border的大小,border为0则它们也为0
四.元素尺寸和位置
适用于比如说网页滑动到达某个元素之后要触发什么事件,这个时候就可以用offsetTop精确知道距离,再根据这个写相应元素滚动事件即可
对比和总结