事件流
事件流就是事件执行过程中的流动过程
捕获阶段:父亲到儿子
冒泡阶段:儿子到父亲
实际上都是冒泡阶段
事件捕获
如果要查看捕获过程,就要使用事件捕获机制,让捕获机制为true
document.addEventListener(事件类型,事件处理函数,true(捕获机制))
事件冒泡
1、冒泡一定会发生的,当一个元素触发事件后,会向上依次调用所有父级的同名事件(同一类型的事件,如点击事件)
2、阻止冒泡:禁止触发儿子事件后导致父级同名事件冒泡
阻止冒泡就要用到事件对象:事件对象.stopPropagetion()
事件解绑
//事件绑定
事件对象.addEventListener(事件类型,事件执行函数)
//事件解绑
事件对象.removeEventListener(事件类型,事件执行函数)
注意的是:匿名函数无法解绑事件,所以在绑定事件的时候的事件执行函数不能用匿名函数
事件委托
1、事件委托可以减少注册次数,只要给父亲绑定事件,通过点击儿子然后冒泡到父亲(孩子有很多个但是父亲只有一个),这样可以减少了给绑定孩子事件。(虽然孩子没有绑定事件,但是它会冒泡到父亲身上)
2、如果想要使得孩子发生变化,那么就要用到事件对象,e.target就是获取到的是当前选中的孩子(但是获取的是所有的孩子)
3、如果只想让指定类型的孩子发生变化,那么就要用到e.target.tagName='类名'(指定你想要获取的孩子类型如LI)
4、案例:电梯导航栏(注意的是:排他思想,如果想要排除哪一个元素,一定要在事件里面定义获取这个对象,不要在事件外面定义!!!!!!!一开始要判断这个对象有没有,没有就添加类,有就移除,页面丝滑滚动: scroll-behavior: smooth;选中自定义属性盒子的写法document.querySelector([data-name=first]
))
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
}
ul {
list-style: none;
}
html {
/* 让滚动条丝滑滚动 */
scroll-behavior: smooth;
}
.besider_top_nav {
margin: 0 auto;
width: 100%;
background-color: antiquewhite;
height: 100px;
text-align: center;
}
.besider_hot,
.besider_first,
.besider_second,
.besider_footer {
text-align: center;
margin: 0 auto;
width: 800px;
height: 300px;
background-color: aqua;
}
.besider_first {
height: 500px;
background-color: aquamarine;
}
.besider_second {
height: 400px;
background-color: bisque;
}
.besider_footer {
height: 800px;
}
.besider_besider {
display: flex;
position: fixed;
flex-direction: column;
top: 150px;
right: 150px;
width: 100px;
height: 500px;
background-color: cadetblue;
}
.besider_besider li {
flex: 1;
line-height: 100px;
text-align: center;
align-items: center;
color: #fff;
}
.besider_besider .active {
color: blueviolet;
z-index: 999;
}
</style>
</head>
<body>
<div class="besider_top_nav">
顶部导航栏
</div>
<div class="besider_hot">
商品热卖
</div>
<div class="besider_first">
第一模块
</div>
<div class="besider_second">
第二模块
</div>
<div class="besider_footer">
底部模块
</div>
<ul class="besider_besider">
<li data-name="top_nav">顶部导航栏</li>
<li data-name="hot">商品热卖</li>
<li data-name="first">第一模块</li>
<li data-name="second">第二模块</li>
<li data-name="footer">底部模块</li>
</ul>
<script>
const besider = document.querySelector('.besider_besider')
//1、点击小盒子然后对应大盒子页面能够滚动
besider.addEventListener('click', function (e) {
const active = document.querySelector('.besider_besider .active')
if (active) {
active.classList.remove('active')
}
e.target.classList.add('active')
//点击不同文字跳到对应的盒子
//获取大盒子,先获取类名对应到不同的盒子,找他们的共同点
console.log(e.target.dataset.name);
const box = document.querySelector(`.besider_${e.target.dataset.name}`)
// console.log(box.offsetTop);
document.documentElement.scrollTop = box.offsetTop
})
//大盒子页面滚动对应小盒子文字颜色变化
window.addEventListener('scroll', function () {
//排他思想
const active = document.querySelector('.besider_besider .active')
if (active) {
active.classList.remove('active')
}
const besider_top_nav = document.querySelector('.besider_top_nav')
const besider_hot = document.querySelector('.besider_hot')
const besider_first = document.querySelector('.besider_first')
const besider_second = document.querySelector('.besider_second')
const besider_footer = document.querySelector('.besider_footer')
if (document.documentElement.scrollTop >= besider_top_nav.offsetTop && document.documentElement.scrollTop < besider_hot.offsetTop) {
document.querySelector(`[data-name=top_nav]`).classList.add('active')
}
if (document.documentElement.scrollTop >= besider_hot.offsetTop && document.documentElement.scrollTop < besider_first.offsetTop) {
document.querySelector(`[data-name=hot]`).classList.add('active')
}
if (document.documentElement.scrollTop >= besider_first.offsetTop && document.documentElement.scrollTop < besider_second.offsetTop) {
document.querySelector(`[data-name=first]`).classList.add('active')
}
if (document.documentElement.scrollTop >= besider_second.offsetTop && document.documentElement.scrollTop < besider_footer.offsetTop) {
document.querySelector(`[data-name=second]`).classList.add('active')
}
if (document.documentElement.scrollTop >= besider_footer.offsetTop) {
document.querySelector(`[data-name=footer]`).classList.add('active')
}
})
</script>
</body>
</html>
阻止默认行为
在如提交表单的时候,如果信息不正确那么就提交不了表单,这时候就要阻止默认行为(e.preventDefault())
页面加载事件
这个不仅可以监听整个页面资源加载完毕,也能够针对某个对象绑定 load事件(比如要等到一个事件加载完毕之后再执行
window.addEventListener('load',function(){
//页面加载完之后执行的函数(往往用在页面内容很多的情况下)
})
//也可以针对某个对象
对象.addEventListener('load',function(){
//对象加载完之后执行的函数(往往用在页面内容很多的情况下)
})
还有当页面加载时间过长时,无需等待样式等出现,只要出现文本标签,那么就用
document.addEventListener('DOMContentLoaded',function(){
//页面加载执行的函数(往往用在想要在加载时间过长只要出现文本标签的情况)
})
页面滚动事件
①页面滚动:scroll
②获取页面滚动的距离:
1)对象.scrollTop//页面被卷去的头部(就是在一个盒子里面,盒子有滚动条,然后滚动盒子内容,获得滚动条的移动高度)(可写)
2)document.documentElement.scrollTop// 页面HTML被卷去的高度,返回的是数字型,没有单位
页面尺寸事件
页面尺寸发生变化:resize
client家族和offset家族
①clientWidth:获得盒子的宽度(不包含边框)(只读)
②offset家族(包含边框)
1)offsetWidth:获得盒子距离父亲的宽度(如果盒子没有定位,那么就是距离整个window的宽度)(只读)
2)offsetTop:获得盒子距离父亲的高度(如果想知道距离父亲的高度,一定要给父亲加定位!!!)(只读)
③案例(伪代码,其中样式省略了)
<ul class="tab">
<li>导航栏1</li>
<li>导航栏2</li>
<li>导航栏3</li>
<li>导航栏4</li>
<li>导航栏5</li>
</ul>
<div class="bottom_line">
</div>
const lis = document.querySelectorAll('.tab li');
const bottom_line = document.querySelector('.bottom_line')
for (let i = 0; i < lis.length; i++) {
lis[i].addEventListener('click', function (e) {
console.log(lis[i].offsetLeft);
str = lis.offsetLeft;
//注意(移动的便宜用字符串)要这样写!!!!!
bottom_line.style.transform = `translateX(${lis[i].offsetLeft}px )`;
})
}
补充
属性选择器:
/* 三个输入框字体都是红色
input {
color: red;
} */
/* 只有text的文本框字体才会变色
input[type=text] {
color: aquamarine;
} */
/* 只有属性值为123的文本框才能够被选出来 */
input[value='123'] {
color: blue;
}
<input type="text">
<input type="password">
<input type="text" value="123">