1.事件流
事件流指的是事件完整执行过程中的流动路径 (事件触发后产生的流程)
事件流分为两个阶段
1.捕获阶段
从dom的根元素开始去执行对应的事件(从外到里)
事件捕获需要写对应代码才能看到结果
DOM.addEventListener(事件类型,事件处理函数,是否使用捕获机制)
addEventListener第三个参数传入true代表是捕获阶段触发(很少使用);若传入false代表冒泡阶段触发,默认就是false(开启一个阶段另一个阶段也是存在的)
2.冒泡阶段
(从目标元素开始)当一个元素执行了这个事件,它会一级一级的往上冒泡,会依次向上调用所有父级元素的同名事件。父级元素也会执行事件)
事件捕获阶段执行方向相反(从外到内);事件监听第三个元素默认是false(冒泡阶段)
const son = document.querySelector('.son')
document.addEventListener('click', function () {
alert('我是爷爷')
}, true)
father.addEventListener('click', function () {
alert('我是粑粑')
}, true)
son.addEventListener('click', function () {
alert('我是儿子')
}, true)
2.事件冒泡
当一个元素的事件被触发时,同样的事件(同名事件)将会在该元素的所有祖先元素中一次被触发,这一过程被称为事件冒泡
简单理解:当一个元素触发事件后,会依次向上调用所有父级元素的 同名事件
const son = document.querySelector('.son')
document.addEventListener('click',function(){
alert('我是爷爷')
})
father.addEventListener('click',function(){
alert('我是粑粑')
})
son.addEventListener('click',function(){
alert('我是儿子')
})
3.阻止冒泡
因为默认就有冒泡模式的存在,所以容易导致事件影响到父级元素。若想把事件就限制在当前元素内,就需要阻止事件冒泡。
阻止事件冒泡需要拿到事件对象
语法:事件对象.stopPropagation()
此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效
阻止哪个事件就在哪个事件添加
const div = document.querySelector('div')
const p = document.querySelector('p')
p.addEventListener('click',function(e){
console.log('p');
// 阻止p冒泡到div
// 阻止冒泡:
// 事件对象.stopPropagation()
e.stopPropagation()
})
div.addEventListener('click',function(){
console.log('div');
})
4.事件对象其他方法
阻止默认行为(比如a链接跳转之后的跳转)
<script>
// 点击a,打印内容,并且不能跳转
const a = document.querySelector('a')
a.addEventListener('click',function(e){
// a点击之后,阻止默认行为
// 事件对象.preventDefault();
e.preventDefault()
})
</script>
5.两种注册事件写法
1.on事件:同类型的事件只能注册1个,无法开启捕获,只能默认冒泡
两个同类型的事件,后面的会覆盖前面的
const btn1 = document.querySelector('.btn1')
btn1.onclick = function(){
alert('点击了')
// 解绑事件
// 元素.onclick = null
btn1.onclick = null//只执行一次
}
btn1.onclick = function(){
alert('点击第二次')//两个同类型的事件,后面的覆盖前面的
}
2.事件监听:同类型的事件可以注册多个
元素.removeEventListener('事件类型',事件处理函数的名称) 移除某一个事件
const btn2 = document.querySelector('.btn2')
const f1 = function(){
console.log('a');
}
const f2 = function(){
console.log('b');
}
const f3 = function(){
console.log('c');
}
btn2.addEventListener('click',f1)
btn2.addEventListener('click',f2)
btn2.addEventListener('click',f3)
// 解绑事件
// 匿名函数无法被解绑
// 元素.removeEventListener('事件类型',事件处理函数的名称) 移除某一个事件
btn2.removeEventListener('click',f1)
6.鼠标经过事件
mouseover 和 mouseout 会有冒泡效果
mouseenter 和 mouseleave 没有冒泡效果 (推荐)
7.事件委托
给父元素注册事件,当我们触发子元素的时候,会发生事件冒泡到父元素身上
事件委托流程:(把事件注册给上级元素)
1.给上级元素注册事件
2.利用事件对象.target找到目标元素
3.判断目标对象标签名是不是我要找的。用tagName:获取标签名:注意是大写的
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ul>
const ul = document.querySelector('ul')
ul.addEventListener('click',function(e){
// 找到目标元素(最先触发事件的元素)
// 事件对象.target找到目标元素
//看看是否是我们要找到的目标元素 e.target li
//找到对象的标签名 e.target.tagName LI
if(e.target.tagName === 'LI'){
e.target.style.background = 'red'
}
})
案例
<script>
// 1.给父元素注册事件,当我们触发某一个子元素的时候,会发生事件冒泡到父元素身上
// 获取父元素
const div = document.querySelector('div')
// 事件监听
div.addEventListener('click',function(e){
// 看看是否是我们要找到的目标元素
if(e.target.tagName === 'P'){
e.target.style.background = 'plum'
}
})
</script>
8.页面加载事件
load:加载外部资源(如图片、外联CSS和JavaScript等)加载完毕时触发的事件
监听页面所有的资源加载完毕,给window添加监听事件。 当你把代码写在前面的时候,一般用window,当页面所有资源加载完毕执行
<body>
<img src="./images/b04.jpg" alt="">
<script>
// 加载事件:当资源加载完毕执行的事件
// load
// 监听页面所有的资源加载完毕,给window添加监听事件
// 当你吧代码写在前面的时候,一般用window,当页面所有资源加载完毕执行
window.addEventListener('load',function(){
console.log('所有资源');
})
</script>
<script>
// DOMContentloaded
// 给document加
// 无需等待样式表,图像等完全加载
window.addEventListener('load',function(){
console.log('window');
})
document.addEventListener('DOMContentload',function(){
console.log('document');
})
</script>
9.页面滚动事件
事件名:scroll 滚动条在滚动的时候持续触发的事件
滚动事件、滚动条滚动的时候触发,谁有滚动条加给谁
// 滚动条在滚动的时候持续触发的事件
// 很多网页
// 事件名:scroll
// 滚动事件、滚动条滚动的时候触发,谁有滚动条加给谁
const div = document.querySelector('div')
div.addEventListener('scroll',function(){
// alert('你好呀')
// scrollTop返回的是上边卷进去的距离
console.log(div.scrollTop);
})
// 点击button回到顶部
const button = document.querySelector('button')
button.addEventListener('click',function(){
// 回到顶部就是卷进去的距离为0
// div.scrollTop可以返回也可以设置
div.scrollTop = 0
})
</script>
10.scroll事件
<!DOCTYPE html>
<html lang="en">
<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>
body{
height: 3000px;
background:linear-gradient(pink,purple);
}
</style>
</head>
<body>
<script>
// scroll:
// 如果整个窗口具有滚动条,那么滚动事件加给窗口window
window.addEventListener('scroll',function(){
// 如果整个页面往上卷,那么这个事件是html的,这个scrollTop找html获取
console.log(document.documentElement.scrollTop);
})
</script>
</body>
</html>
11.获取元素的位置
offsetLeft和offsetTop
获取距离为依据定位的父级元素,如果父级没有定位,那么以(文档左上角)浏览器定位
相对于定位元素的位置
12.属性选择器
<html lang="en">
<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>
/* 属性选择器 */
/* 匹配带有id属性的选择器 */
[id]{
background: red;
}
[class=c1]{
background-color: plum;
}
</style>
</head>
<body>
<div id="1">1</div>
<div class="c1">2</div>
<div id="c2">3</div>
<p class="c3">6</p>
</body>
</html>