web API
全选反选案例
需求:
- 勾选大复选框,勾选全部小复选框
- 取消勾选大复选框,则取消勾选全部小复选框
- 若有小复选框没有被勾选,则大复选框不被勾选
- 若所有小复选框都被勾选,则大复选框被勾选
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
* {
margin: 0;
padding: 0;
}
table {
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #c0c0c0;
width: 500px;
margin: 100px auto;
text-align: center;
}
th {
background-color: #09c;
font: bold 16px "微软雅黑";
color: #fff;
height: 24px;
}
td {
border: 1px solid #d0d0d0;
color: #404060;
padding: 10px;
}
.allCheck {
width: 80px;
}
</style>
</head>
<body>
<table>
<tr>
<th class="allCheck">
<input type="checkbox" name="" id="checkAll"> <span class="all">全选</span>
</th>
<th>商品</th>
<th>商家</th>
<th>价格</th>
</tr>
<tr>
<td>
<input type="checkbox" name="check" class="ck">
</td>
<td>小米手机</td>
<td>小米</td>
<td>¥1999</td>
</tr>
<tr>
<td>
<input type="checkbox" name="check" class="ck">
</td>
<td>小米净水器</td>
<td>小米</td>
<td>¥4999</td>
</tr>
<tr>
<td>
<input type="checkbox" name="check" class="ck">
</td>
<td>小米电视</td>
<td>小米</td>
<td>¥5999</td>
</tr>
</table>
<script>
//1.获得事件源及响应对象
//1.1获得大复选框
const checkAll = document.querySelector('#checkAll')
//1.2获得小复选框
const ck = document.querySelectorAll('.ck')
//2.在大复选框上绑定事件
checkAll.addEventListener('click', function () {
if (checkAll.checked === true) {
for (let i = 0; i < ck.length; i++) {
ck[i].checked = true
}
} else {
for (let i = 0; i < ck.length; i++) {
ck[i].checked = false
}
}
})
//3.全选后,若小复选框中有一个没有勾选,大复选框的勾选状态需要取消
//3.1用计时器进行判断是一种方法
// setInterval(function () {
// let a = 0
// for (let i = 0; i < ck.length; i++) {
// if (ck[i].checked === false) {
// checkAll.checked = false
// }
// if (ck[i].checked === true) {
// a++
// }
// }
// if (a === ck.length) {
// checkAll.checked = true
// }
// }, 500)
//3.2为每个小复选框添加点击事件,并判断有checked的个数是否等于总的小复选框的个数
for (let i = 0; i < ck.length; i++) {
ck[i].addEventListener('click', function () {
if (document.querySelectorAll('.ck:checked').length === ck.length) {
checkAll.checked = true
}
else {
checkAll.checked = false
}
})
}
</script>
</body>
</html>
事件流
事件完整执行过程中的流动路径
父元素==>子元素 -----事件捕获 |
---|
子元素==>父元素 ------事件冒泡 |
实际工作都是使用事件冒泡为主
事件捕获
从DOM根元素开始执行对应事件(需要写出对应的回调寒素才可以看到捕获机制的效果)
DOM.addEventListener(事件类型,函数,是否使用捕获)
是 — 捕获机制
否 — 冒泡机制
事件冒泡
当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中触发
【有时怕点击父元素中的子元素但父元素没有反应,则可以利用该机制】
阻止冒泡
事件对象.stopPropagation()
(对捕获同样有效)
阻止元素默认行为
如表单提交,链接跳转 — 【可用于表单信息有误,不规范以及链接跳转需同意相关协议】
解绑事件
L0事件 | 对象.onclick = null |
---|---|
L2事件 | 对象.removeEventListener(‘事件类型’,函数) |
匿名函数无法被解绑
[!IMPORTANT]
鼠标经过事件区别
- 有冒泡:
mouseover mouseout
- 无冒泡:
mouseenter mouseleave
事件委托
利用事件冒泡特征解决开发需求 ==> 将事件委托给父元素
作用:
减少子元素注册事件的次数,提高程序性能
e.target.tagName
实际触发事件的对象的标签名 【为大写】
e.target
— 实际的触发事件的对象
案例:
事件委托版tab栏切换
<script>
//1.获取li的父元素ul
const ul = document.querySelector('.tab-nav ul')
//2.绑定事件
ul.addEventListener('mouseover', function (e) {
if (e.target.tagName === 'A') {
//排他
document.querySelector('.tab-nav ul .active').classList.remove('active')
//添加
e.target.classList.add('active')
//下面的大盒子模块
const i = +e.target.dataset.id
//排他
document.querySelector('.tab-content .active').classList.remove('active')
//添加
document.querySelector(`.tab-content div:nth-child(${i + 1})`).classList.add('active')
}
})
</script>
其他事件
页面加载事件
— 有时js想写在body的上边 —
load DOMContentLoaded
区别:
load | 可用在任何对象加载完毕时调用 |
---|---|
DOMContentLoaded | 只可用在document对象,表示html元素加载完毕后执行 |
页面滚动事件
scroll
—给window或document
应用场景:固定导航条,返回顶部
元素的两个属性:
scrollTop scrollLeft
---- 可读写
案例
小兔显示导航和回到顶部
<script>
//获取响应对象
const dt = document.querySelector('.xtx-elevator')
const backTop = document.querySelector('.xtx-elevator #backTop')
//1.当页面滚动大于300px,显示侧边导航
window.addEventListener('scroll', function () {
const n = document.documentElement.scrollTop
// if (n >= 300) {
// dt.style.opacity = 1
// } else {
// dt.style.opacity = 0
// }
dt.style.opacity = n >= 300 ? 1 : 0
})
//点击返回页面顶部
backTop.addEventListener('click', function () {
document.documentElement.scrollTop = 0
})
</script>
页面尺寸事件
resize
—窗口尺寸改变
clientWidth clientHeight
—元素的宽高(不含border,margin,滚动条)
window.addEventListener('resize', function () {
let w = document.documentElement.clientWidth
console.log(w);
})
元素尺寸和位置
场景:页面滚动到某个元素的位置,触发函数调用
offsetWidth offsetHeight
—包含border(数值)
如果盒子隐藏,获取结果为0
offsetLeft offsetTop
--元素的位置(只读)【距离定位父级】
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
.father {
overflow: hidden;
width: 500px;
height: 500px;
background-color: skyblue;
/* 当开启相对定位后,div.father为定位父元素,以此为测量基准 */
/* position: relative; */
}
.son {
width: 200px;
height: 200px;
margin-left: 100px;
margin-top: 100px;
background-color: blue;
}
</style>
<body>
<div class="father">
<div class="son"></div>
</div>
<script>
//1.获取事件源
const son = document.querySelector('.son')
console.log(son.offsetLeft);
</script>
</body>
</html>
案例:
仿京东固定导航条案例
- 滚动事件
- 到一定位置,显示顶部导航条
<!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>
* {
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="javascript:;"></a>
</div>
<script>
//获取响应对象元素
const header = document.querySelector('.header')
const sk = document.querySelector('.sk')
//1.为事件源绑定滚动事件
window.addEventListener('scroll', function () {
//1.获取滚动距离参数
const n = document.documentElement.scrollTop
if (n >= sk.offsetTop) {
header.style.top = 0
} else {
header.style.top = '-80px'
}
})
</script>
</body>
</html>
实现哔哩哔哩点击小滑块移动效果
<script>
// 1. 事件委托的方法 获取父元素 tabs-list
const list = document.querySelector('.tabs-list')
const line = document.querySelector('.line')
// 2. 注册点击事件
list.addEventListener('click', function (e) {
// 只有点击了A 才有触发效果
if (e.target.tagName === 'A') {
// console.log(11)
// 当前元素是谁 ? e.target
// 得到当前点击元素的位置
// console.log(e.target.offsetLeft)
// line.style.transform = 'translateX(100px)'
// 把我们点击的a链接盒子的位置 然后移动
line.style.transform = `translateX(${e.target.offsetLeft}px)`
}
})
</script>
补充:
element.getBounding.ClientRect() ===> 返回元素大小及其相对视口的位置
总结尺寸大小