事件流
事件流
概念:事件完整执行过程中的流动路径
阶段:捕获阶段->目标阶段->冒泡阶段
window->document->html->body->div->body->html->document->window
true表示捕获阶段
false表示冒泡阶段
<body>
<div class="box">
<div class="son">son</div>
</div>
<script>
// 事件流->事件完整执行过程中的流动路径
// 捕获阶段->目标阶段->冒泡阶段
// window->document->html->body->div->body->html->document->window
const box = document.querySelector('.box')
const son = document.querySelector('.son')
/* window.addEventListener(
'click',
function () {
console.log('window')
},
true
) // true表示捕获阶段 */
document.addEventListener(
'click',
function () {
console.log('document')
},
true
)
document.documentElement.addEventListener(
'click',
function () {
console.log('html')
},
true
)
document.body.addEventListener(
'click',
function () {
console.log('body')
},
true
)
box.addEventListener(
'click',
function () {
console.log('box')
},
true
)
son.addEventListener('click', function () {
console.log('son')
})
son.addEventListener(
'click',
function () {
console.log('son')
},
true
)
window.addEventListener(
'click',
function () {
console.log('window')
},
false
) // false表示冒泡阶段
document.addEventListener('click', function () {
console.log('document')
})
document.documentElement.addEventListener('click', function () {
console.log('html')
})
document.body.addEventListener('click', function () {
console.log('body')
})
box.addEventListener('click', function () {
console.log('box')
})
</script>
</body>
冒泡阶段
冒泡的概念: 触发元素,其自己及其祖先元素都会触发。
<body>
<div class="box">
<div class="son">son</div>
</div>
<script>
// 事件流->事件完整执行过程中的流动路径
// 捕获阶段->目标阶段->冒泡阶段
// 冒泡 触发元素,他自己及其祖先元素都会触发
const box = document.querySelector('.box')
const son = document.querySelector('.son')
son.addEventListener('click', function () {
console.log('son')
alert('son')
})
box.addEventListener('click', function () {
console.log('box')
alert('box')
})
</script>
</body>
事件委托
事件委托又称事件委派、事件代理 - 利用冒泡
概念:给元素祖先绑定事件,将来子元素触发事件 会冒泡到祖先元素,
优点:1 .提高代码执行效率
2 .对动态生成的子元素也生效
<!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>
*{
list-style: none;
}
</style>
</head>
<body>
<ul>
<li>111</li>
<li>222</li>
<li>333</li>
<li>444</li>
<li>555</li>
</ul>
<script>
// 事件委托、事件委派、事件代理 - 利用冒泡
// 给元素祖先绑定事件,将来子元素触发事件 会冒泡到祖先元素,
//1 提高代码执行效率 2 对动态生成的子元素也生效
const ul = document.querySelector('ul')
ul.addEventListener('click', function (e) {
console.log('ul')
console.log(e.target) // 真正触发的元素
e.target.style.backgroundColor = 'red'
})
// 直接操作儿子缺点 无法获取后面动态生成的元素
</script>
</body>
</html>
阻止事件冒泡
在JavaScript中,如果要阻止事件冒泡,可以使用 `stopPropagation()` 方法。此方法可以阻止事件继续传播到父级元素。
例如,如果要阻止元素的 `click` 事件冒泡到父级元素,可以按照以下方式使用 `stopPropagation()` 方法:
element.addEventListener('click', function(event) {
event.stopPropagation();
// 这里可以写点击事件的处理逻辑
});
事件解绑
可以分为:
解绑dom0级事件
- 语法 事件源.on事件类型 = null
解绑dom2级事件
- 语法 事件源.removeEventListener('事件类型', 要解绑的事件处理函数)
- 注意 如果用dom2级解绑, 绑定的时候的事件处理函数必须要在外面单独定义,用函数名的形式进行绑定
<!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>
</head>
<body>
<button>dom0级事件</button>
<button>dom2级事件</button>
<script>
const btn = document.querySelectorAll('button')
btn[0].onclick = function () {
alert('dom0')
btn.onclick = null
}
function f() {
alert('dom2')
// 解除事件绑定
btn[1].removeEventListener('click', f)
}
btn[1].addEventListener('click', f)
</script>
</body>
</html>
阻止默认行为
默认行为
1 超链接点击 默认会跳转
阻止默认行为方法(高级浏览器/w3c标准的):event.preventDefault()
2 form表单提交
除了a的默认跳转行为,其实表单的提交行为很多时候我们也要进行阻止,当然是因为有表单验证了,因为输入问题而去阻止提交:
<!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>
</head>
<body>
<form action="https://www.baidu.com">
<input type="text" name="username" />
<button>按钮</button>
</form>
<a href="https://www.baidu.com">百度</a>
<script>
// 默认行为 超链接点击 默认会跳转
const alink = document.querySelector('a')
const form = document.querySelector('form')
const ipt = document.querySelector('input[name=username]')
alink.addEventListener('click', function (e) {
e.preventDefault() // 阻止跳转
alert('ok')
})
form.addEventListener('submit', function (e) {
if (ipt.value.trim() === '') {
e.preventDefault() // 阻止默认跳转
}
})
</script>
</body>
</html>
窗口加载事件
window.onload是窗口(页面)加载事件,当文档内容完全加载完成会触发该事件(包括图像、脚本文件、CSS文件等),就调用的处理函数;
有了window.onload就可以把JS代码写到页面元素的上方,因为onload是等页面内容全部加载完毕,再去执行处理函数;
window.onload传统注册事件方式只能写一次,如果有多个,会以最后-个window.onload为准;
如果使用addEventListener则没有限制;
<!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>
<script>
// 窗口加载 onload
// 文档全部加载完毕 包括css 图片 js等资源
// window.addEventListener('load', function () {
// // 给按钮绑定单击事件
// const btn = document.querySelector('button')
// console.log(btn)
// btn.addEventListener('click', function () {
// alert('中国人民万岁')
// })
// })
// DOMContentLoaded 当dom元素加载完毕就执行 不必等其他资源加载完
document.addEventListener('DOMContentLoaded', function () {
// 给按钮绑定单击事件
const btn = document.querySelector('button')
console.log(btn)
btn.addEventListener('click', function () {
alert('中国人民万岁')
})
})
</script>
</head>
<body>
<button>按钮</button>
</body>
</html>
窗口尺寸事件
1 事件resize在窗口大小改变时触发,可以用于响应窗口大小的变化并执行相应的操作。这个事件通常用于调整页面布局或重新计算元素尺寸,以适应不同的窗口大小。
元素的尺寸和位置
元素的尺寸,位置相关:
-
element.offsetLeft
-
element.offsetTop
-
element.clientWidth
-
element.clientHeight
-
element.offsetWidth
-
element.offsetHeight
<!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>
.wrapper {
width: 300px;
height: 300px;
background-color: red;
padding: 20px;
border: 6px dashed black;
}
.wrapper .box {
width: 100px;
height: 100px;
background-color: blue;
margin: 0 auto;
border: 2px solid green;
padding: 10px;
overflow: hidden;
white-space: nowrap;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="box">
内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容
</div>
</div>
<script>
// 元素尺寸或位置 client offset scroll
const wrapper_box = document.querySelector('.wrapper')
const box = document.querySelector('.box')
console.log(wrapper_box.clientWidth) // width + 左右padding 340
console.log(wrapper_box.clientHeight)
console.log(box.clientWidth) //
console.log(box.clientHeight)
console.log('=====================')
console.log(wrapper_box.offsetWidth) // width + 左右padding 340
console.log(wrapper_box.offsetHeight)
console.log(box.offsetWidth) // 带边框的clientWidth
console.log(box.offsetHeight)
console.log('=====================')
console.log(box.scrollWidth) // 实际内容区域(包括隐藏的内容)
</script>
</body>
</html>
窗口滚动事件
style>
body {
height: 3000px;
}
</style>
</head>
<body>
<script>
window.addEventListener('scroll', function () {
console.log(document.documentElement.scrollTop) // 页面被卷去的尺寸
})
</script>
</body>