Web APIs 3(事件流、事件委托)
1.事件流
- 事件流:事件完整执行过程中的流动路径
- 捕获阶段:从DOM根元素开始去执行对应的事件(从外到里)
DOM.addEventListener(事件类型,事件处理函数,是否使用捕获机制)
eg : 分别给document、父级div、子机div都注册同一个事件监听,则从外到内执行
-
冒泡阶段:当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发(当一个元素触发事件后,会依次向上调用所有父级元素的同类型事件)
-
阻止冒泡:
- 问题:默认有冒泡模式的存在,容易导致事件影响父级元素
- 需求:想把事件就限制在当前元素内,需要阻止事件冒泡
- 前提:阻止事件冒泡要先拿到事件对象
- 语法:阻止事件流,不仅对冒泡有用,对捕获也有用
事件对象.stopPropagation()
示例:点击son盒子时,事件流被阻止,只会弹出“我是儿子”
html"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .father { width: 400px; height: 400px; background-color: aqua; } .son { width: 200px; height: 200px; background-color: blueviolet; } </style> </head> <body> <div class="father"> <div class="son"></div> </div> <script>html" title=javascript>javascript"> const fa = document.querySelector('.father') const son = document.querySelector('.son') document.addEventListener('click', function () { alert('我是爷爷') }) fa.addEventListener('click', function () { alert('我是爸爸') }) son.addEventListener('click', function (e) { alert('我是儿子') e.stopPropagation() }) </script> </body>
-
解绑事件
元素.removeEventListener(‘事件类型’,事件处理函数)
- 注意:匿名函数无法被解绑
btn.removeEventListener('click',函数名)
2.事件委托
-
优点:减少时事件监听注册的次数,提高程序性能
-
原理:利用事件冒泡的特点,给父元素注册事件,当我们触发子元素的时候,会冒泡到父元素身上,从而触发父元素的事件
-
实现:事件对象.target可以获得真正触发事件的元素
html"><body> <ul> <li>第1个孩子</li> <li>第2个孩子</li> <li>第3个孩子</li> <li>第4个孩子</li> <li>第5个孩子</li> <p>我不需要变色</p> </ul> <script>html" title=javascript>javascript"> const ul = document.querySelector('ul') ul.addEventListener('click', function (e) { console.log(e.target); //点击的对象 //只要点li变色,p不要变色 if (e.target.tagName === 'LI') { e.target.style.color = 'red' } }) </script> </body>
-
阻止默认行为的发生:e.preventDefault()
eg:点击提交默认直接提交,但表单信息有误时不允许提交,就需要使用该阻止方式
html"><body> <form action="http://www.baidu.com"> <input type="submit" value="提交"> </form> <script>html" title=javascript>javascript"> const form = document.querySelector('form') form.addEventListener('click', function (e) { e.preventDefault() }) </script> </body>
3.其他事件
-
页面加载事件
- 定义:加载外部资源(如图片、外联CSS、JavaScript)加载完毕时触发的事件
- 使用场景:需要等页面资源全部处理完再做一些事情,eg:如果将script代码写到head中,直接找dom元素找不到
- load事件:监听页面所有资源加载完毕:给window添加load事件(当然也可以给针对某个资源绑定load事件)
html"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script>html" title=javascript>javascript"> //等待页面所有资源加载完毕就会执行回调函数 window.addEventListener('load', function () { const btn = document.querySelector('button') btn.addEventListener('click', function () { alert("你好") }) }) </script> </head> <body> <button>点击</button> </body>
- DOMContentLoaded事件:当HTML文档被完全加载和解析完后,无需等待样式表、图像等完全加载:给document添加DOMContenLoaded事件
-
元素滚动事件
- 滚动条滚动触发的事件
- scroll事件:监听整个页面滚动(也可以监听某个元素滚动)
<script> window.addEventListener('scroll', function () { console.log("滚动") }) </script>
- 获取滚动位置的属性:scrollLeft|scrollTop(可读写)
<script> const div = document.querySelector('div') window.addEventListener('scroll', function () { //document.documentElement返回HTML元素 const n = document.documentElement.scrollTop console.log(n) if (n >= 100) { div.style.display = 'block' } else { div.style.display = 'none' } }) </script>
- 滚动到指定坐标:元素.scrollTo(x,y)
-
页面尺寸事件
- 窗口尺寸发生改变时触发事件
- resize
<script> window.addEventListener('resize', function () { console.log(11); }) </script>
- 检测屏幕尺寸——获取元素宽高
- clientWidth、clientHeight(不包含边框,margin,滚动条等,只读)
4.元素尺寸位置
- 获取宽高:offsetWidth和offsetHeight(包含边框,只读)
- 获取位置:offsetLeft和offsetTop(只读):元素距离父级元素左上距离
案例:实现滚动到秒杀模块位置后,顶部导航滑动出现,再返回到秒杀模块上方后,顶部导航隐藏
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.content {
overflow: hidden;
width: 1000px;
height: 3000px;
background-color: pink;
margin: 0 auto;
}
.backtop {
display: none;
width: 50px;
left: 50%;
margin: 0 0 0 505px;
position: fixed;
bottom: 60px;
z-index: 100;
}
.backtop a {
height: 50px;
width: 50px;
background: url(./images/bg2.png) 0 -600px no-repeat;
opacity: 0.35;
overflow: hidden;
display: block;
text-indent: -999em;
cursor: pointer;
}
.header {
position: fixed;
top: -80px;
left: 0;
width: 100%;
height: 80px;
background-color: purple;
text-align: center;
color: #fff;
line-height: 80px;
font-size: 30px;
transition: all .3s;
}
.sk {
width: 300px;
height: 300px;
background-color: skyblue;
margin-top: 500px;
}
</style>
</head>
<body>
<div class="header">我是顶部导航栏</div>
<div class="content">
<div class="sk">秒杀模块</div>
</div>
<div class="backtop">
<img src="../images/close2.png" alt="">
<a href="html" title=javascript>javascript:;"></a>
</div>
<script>
const sk = document.querySelector('.sk')
const header = document.querySelector('.header')
window.addEventListener('scroll', function () {
const n = document.documentElement.scrollTop
/* if (n >= sk.offsetTop) {
header.style.top = 0
} else {
header.style.top = '-80px'
} */
header.style.top = n >= sk.offsetTop ? 0 : '-80px'
})
</script>
</body>
</html>
- 总结:
属性 | 作用 | 说明 |
---|---|---|
scrollLeft|scrollTop | 被卷去的头部和左侧 | 配合页面滚动使用,可读写 |
clientWidth|clientHeight | 获取元素宽度和高度 | 不包含border,margin,滚动条,用于获取元素大小,只读属性 |
offsetWidth|offsetHeight | 获得元素宽度和高度 | 包含border、padding,滚动条等,只读 |
offsetLeft|offsetTop | 获取元素距离自己定位父级元素的左、上距离 | 获取元素位置的时候使用,只读 |