关于这一part还没写完 这一系列内容太抽象有点费时间 大家看到了可以先收藏 内容目前正在不断更新编辑中…
事件流
事件流指的是事件完整执行过程中的流动路径
分为捕获阶段和冒泡阶段
以冒泡阶段为主;也及就是没有加捕获机制的也要想着有冒泡阶段
简单来说: 捕获阶段是从大到小;冒泡阶段是从大到小
事件捕获
语法:Dom.addEventListener(事件类型,事件处理函数,是否使用捕获机制)
定义:从Dom的根元素开始去执行对应的事件 根据辈分从大到小执行
具体来说:当触发事件捕获阶段,因为是与事件有关,所以必须用到addEventListener,具体是与该方法中第三个参数有关,默认是false,所以使用时候应该为Dom.addEventListener(事件类型,事件处理函数,true)
触发顺序:
在加入了事件捕获阶段,在触发相同事件时,无论是点击子元素,还是父元素,执行的顺序一定是从父到子,也就是先alert爷爷
<script>
const father = document.querySelector('.father')
const son = document.querySelector('.son')
document.addEventListener('click', function () {
alert('我是爷爷')
}, true)
father.addEventListener('click', function () {
alert('我是爸爸')
}, true)
son.addEventListener('click', function () {
alert('我是儿子')
}, true)
</script>
事件冒泡
定义:当一个元素的事件被触发时,同样的事件会从该元素以及该元素的祖先元素从小到大 的所有祖先元素中依次被触发。这一过程被称为事件冒泡。
执行的结果,如果点击儿子模块,执行的顺序分别为 我是儿子 我是爸爸 我是爷爷;点击爸爸模块,执行顺序是我是爸爸 我是爷爷;也就是符合事件冒泡的触发顺序。
<div class="dad">
<div class="son"></div>
</div>
<script>
const dad = document.querySelector('.dad')
const son = document.querySelector('.son')
document.addEventListener('click', function () {
alert('我是爷爷')
})
dad.addEventListener('click', function () {
alert('我是爸爸')
})
son.addEventListener('click', function () {
alert('我是儿子')
})
</script>
事件冒泡的必要性
如果没有事件冒泡,那么如果存在给大盒子添加点击事件,那么在点击小盒子的时候,就没办法触发大盒子的点击
引出:事件委托:自己不注册事件,将对应的事件注册给祖先元素,减少事件的注册,提高效率
事件的触发要么是冒泡要么是捕获
没有.true,就会出现冒泡触发
也就是我给一个大盒子添加了点击事件,因为它是事件冒泡,所以我在点击小盒子时,也会触发点击事件的函数
<div class="father">
<div class="son"></div>
</div>
<script>
const father = document.querySelector('.father')
const son = document.querySelector('.son')
document.addEventListener('click', function () {
alert('我是爷爷')
})
father.addEventListener('click', function () {
alert('我是爸爸')
})
son.addEventListener('click', function (e) {
alert('我是儿子')
})
</script>
通过mouseover和mouseleave的区别来体现事件冒泡的必要性:
mouseover+mouseout有冒泡效果 也就是即使鼠标经过的是子元素也会触发点击事件;
因为有冒泡的效果,所以在鼠标经过子元素(紫色盒子)时,通过冒泡,就会触发父元素鼠标经过事件,所以就会有鼠标经过。
<div class="dad">
<div class="baby"></div>
</div>
<script>
const dad = document.querySelector('.dad')
dad.addEventListener('mouseover', function () {
console.log('鼠标经过')
})
dad.addEventListener('mouseout', function () {
console.log('鼠标离开')
})
</script>
mouseenter+mouseleave没有冒泡效果
所以在经过子元素和父元素时,子元素属于父元素的一部分,所以不会有鼠标经过和离开的反复横跳
<script>
const dad = document.querySelector('.dad')
dad.addEventListener('mouseenter', function () {
console.log('鼠标经过')
})
dad.addEventListener('mouseleave', function () {
console.log('鼠标离开')
})
</script>
阻止冒泡
步骤:
1.先要明确给哪一块区域冒泡
2.需要对这块区域阻止什么事件就注册什么事件
3.在事件处理函数中添加事件对象,并添加上 e.stopPropagation()
本质上就是就是不让这个事件触发
son.addEventListener('click', function (e) {
alert('我是儿子')
e.stopPropagation()
})
事件解绑
on事件方式 直接使用null覆盖,就可以实现事件的解绑
<button>点击</button>
<script>
const btn = document.querySelector('button')
btn.onclick = function () {
alert('我点击了')
}
btn.onclick = null
</script>
关于addEventListener事件的解绑 注意:匿名函数无法被解绑
<button>点击</button>
<script>
const btn = document.querySelector('button')
function fn () {
alert('我点击了')
}
btn.addEventListener('click', fn)
btn.removeEventListener('click', fn)
</script>
事件委托
将事件监听委托给父元素统一来处理
原理有待解释更进一步
<ul>
<li>第1个孩子</li>
<li>第2个孩子</li>
<li>第3个孩子</li>
<li>第4个孩子</li>
<li>第5个孩子</li>
</ul>
<script>
const ul = document.querySelector('ul')
ul.addEventListener('click', function (e) {
// console.log('哈哈哈')
// this.style.color = 'red'
//专门用来打印对象
// console.dir(e.target)
console.log(e.target.tagName)
})
</script>
tab栏切换
css设计思路主要难点是:导航栏只有给a标签添加active才会有相关选中的样式,主题内容默认设置为display:none;意思是隐藏并且不占用网页位置;也就是设置只有添加active类样式的才会显示出来。这里这个地方的active不相同,可以去不同的名字来区分。
.tab-nav ul li a.active {
border-color: #e1251b;
color: #e1251b;
}表示给该a标签并且是含有active这个class类的添加样式
①css代码
<style>
* {
margin: 0;
padding: 0;
}
.tab {
width: 590px;
height: 340px;
margin: 20px;
border: 1px solid #e4e4e4;
}
.tab-nav {
width: 100%;
height: 60px;
line-height: 60px;
display: flex;
justify-content: space-between;
}
.tab-nav h3 {
font-size: 24px;
font-weight: normal;
margin-left: 20px;
}
.tab-nav ul {
list-style: none;
display: flex;
justify-content: flex-end;
}
.tab-nav ul li {
margin: 0 20px;
font-size: 14px;
}
.tab-nav ul li a {
text-decoration: none;
border-bottom: 2px solid transparent;
color: #333;
}
.tab-nav ul li a.active {
border-color: #e1251b;
color: #e1251b;
}
.tab-content {
padding: 0 16px;
}
.tab-content .item {
display: none;
}
.tab-content .item.active {
display: block;
}
</style>
②html代码
<div class="tab">
<div class="tab-nav">
<h3>每日特价</h3>
<ul>
<li><a class="active" href="javascript:;" data-id="0">精选</a></li>
<li><a href="javascript:;" data-id="1">美食</a></li>
<li><a href="javascript:;" data-id="2">百货</a></li>
<li><a href="javascript:;" data-id="3">个护</a></li>
<li><a href="javascript:;" data-id="4">预告</a></li>
</ul>
</div>
<div class="tab-content">
<div class="item active"><img src="./images/tab00.png" alt="" /></div>
<div class="item"><img src="./images/tab01.png" alt="" /></div>
<div class="item"><img src="./images/tab02.png" alt="" /></div>
<div class="item"><img src="./images/tab03.png" alt="" /></div>
<div class="item"><img src="./images/tab04.png" alt="" /></div>
</div>
</div>
js样式设置:
- 要求:在点击对应tab栏时,导航栏和主题内容都一一对应;并且之前的选中的状态取消掉
- 思路:获取相关元素,然后利用排他思想(所谓的排他思想就是去掉之前选中的元素,自己“上位“)
③js代码
方法一:使用for循环实现:
<script>
const as = document.querySelectorAll('.tab-nav a')
for (let i = 0; i < as.length; i++) {
as[i].addEventListener('click', function (e) {
document.querySelector('.tab-nav .active').classList.remove('active')
e.target.classList.add('active')
document.querySelector('.tab-content .active').classList.remove('active')
document.querySelector(`.tab-content .item:nth-child(${i + 1})`).classList.add('active')
})
}
</script>
方法二:通过事件委托的形式:
<script>
// 采取事件委托的形式进行tab栏切换
// 1.获取ul父元素 因为ul只有一个
const ul = document.querySelector('ul')
const items = document.querySelectorAll('.tab-content .item')
// 2.添加事件
ul.addEventListener('click', function (e) {
// console.log(e.target)
// console.log(e.target.tagName)
// 我们只有点击了a 才会进行添加类和删除类操作
if (e.target.tagName === 'A') {
// console.log('我选的是a')
// 排他思想 先移除原来的active
document.querySelector('.tab-nav .active').classList.remove('active')
// 当前元素添加active 当前元素示e.target
// this指向ul 不能用this
e.target.classList.add('active')
// console.log(e.target.dataset.id)
const id = +e.target.dataset.id
// 排他思想 先移除原来的active
document.querySelector('.tab-content .active').classList.remove('active')
// 对应的大盒子添加active
// document.querySelector(`.tab-content .tem:nth-child($(i+1))`).classList.add('actve')
items[id].classList.add('active')
}
})
</script>