目录
5. 实现bilibili 点击小滑块移动效果(未看这部分移动端)
1. 全选文本框案例(重点)
伪类选择器 :checked 选择被勾选的复选框
<!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.获取大复选框元素
const all = document.querySelector('#checkAll')
// 2. 获取所有的小复选框
const cks = document.querySelectorAll('.ck')
// 3. 点击大复选框 注册事件
all.addEventListener('click', function () {
// 得到大复选框的选中状态
// console.log(this.checked) //得到的是 true 或 false
// 4. 遍历所有的小复选框,让小复选框的checked = 大复选框的checked
for (let i = 0; i < cks.length; i++) {
cks[i].checked = this.checked
}
})
// 5. 小复选框控制大复选框
for (let i = 0; i < cks.length; i++) {
// 5.1 给所有的小复选框添加点击事件
cks[i].addEventListener('click', function () {
// 判断选中的小复选框个数 是不是等于 总的小复选框个数
// 一定要写到点击里面 因为每次点击要获得新的选中个数
// console.log(document.querySelectorAll('.ck:checked').length)
// console.log(document.querySelectorAll('.ck:checked').length === cks.length)
all.checked = document.querySelectorAll('.ck:checked').length === cks.length
})
}
</script>
</body>
</html>
2. 事件委托版 Tab 栏切换
注意通过自定义属性获得的值是字符串,不能直接进行加法 如e.target.dataset.id + 1进行的是拼串,故须对e.target.dataset.id进行转换。
对于使大盒子的对应元素添加active 类,有两种方法:
1. 直接使用索引获得该DOM对象,注意是第 { i + 1 }个item ,因为 i 是从 0 开始的,这种不需要获得所有的item
document.querySelector(`.tab-content .item:nth-child(${i + 1})`).classList.add('active')
2. 先获得所有的item 对象(此时是一个伪数组),然后根据伪数组下标确定添加active 的元素
items[i].classList.add('active')
在最开始获得元素时须获得 items
const items = document.querySelectorAll('.tab-content .item')
<!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>tab栏切换</title>
<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>
</head>
<body>
<div class="tab">
<div class="tab-nav">
<h3>每日特价</h3>
<ul>
<!-- 为 a 添加自定义属性 data-id -->
<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>
<script>
// 采取事件委托的形式 Tab 栏切换
// 1. 获取 ul 父元素 因为 ul只有一个
const ul = document.querySelector('.tab-nav ul')
// 第二种方法
const items = document.querySelectorAll('.tab-content .item')
// 2. 添加事件
ul.addEventListener('click', function(e){
// console.log(e.target); //e.target 是我们点击的对象
// 只有点击了 a 才会 进行 添加类和删除类操作
if(e.target.tagName === 'A') {
// 排他思想,先移除原来的acitve ,当前元素添加 active
document.querySelector('.tab-nav .active').classList.remove('active')
// 当前元素添加 active this指向的是 ul(谁调用就指向谁),不能用this
e.target.classList.add('active')
// 下面大盒子模块
// console.log(e.target.dataset.id);
const i = +e.target.dataset.id //自定义属性获得的值是字符串,须转换为数值型
// 排他思想,先移除原来的acitve ,对应的大盒子添加 active
document.querySelector('.item.active').classList.remove('active')
// 对应的大盒子添加 active
// 第一种方法,直接添加
// document.querySelector(`.tab-content .item:nth-child(${i + 1})`).classList.add('active')
// 第二种方法,利用items 伪数组下标
items[i].classList.add('active')
}
})
</script>
</body>
</html>
3. 页面滚动显示隐藏侧边栏
刚开始是不显示的,使用的是不透明度 opacity为0
<script>
const ele = document.querySelector('.xtx-elevator')
console.log(ele);
// 给页面添加滚动事件
window.addEventListener('scroll', function () {
// 被卷去的头部大于300
const n = document.documentElement.scrollTop
// if (n >= 300) {
// ele.style.opacity = 1
// } else {
// ele.style.opacity = 0
// }
ele.style.opacity = n >= 300 ? 1 : 0
})
// 点击返回页面顶部
const backTop = document.querySelector('#backTop')
backTop.addEventListener('click', function(){
// document.documentElement.scrollTop = 0
// 或者
window.scrollTo(0, 0)
})
</script>
4. 仿京东固定导航栏案例
手动将页面导航栏的 top 值改为 -80px(80为导航栏的高度,刚开始导航栏不显示)
<!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,刚开始不显示 */
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')
console.log(sk.offsetTop);
// 1. 页面滚动事件
window.addEventListener('scroll', function(){
// 当页面滚动到 秒杀模块的时候,就改变 头部 的top值
// 页面被卷去的头部 >= 秒杀模块的位置 offsetTop
const n = document.documentElement.scrollTop
// if (n >= sk.offsetTo) {
// header.style.top = '0'
// } else {
// header.style.top = '-80px'
// }
header.style.top = n >= sk.offsetTop ? '0' : '-80px'
})
</script>
</body>
</html>
5. 实现bilibili 点击小滑块移动效果(未看这部分移动端)
<script>
// 1. 获取父元素 添加事件委托
const list = document.querySelector('.tabs-list')
const line = document.querySelector('.line')
// 2. 给 a 注册事件
list.addEventListener('click', function(e){
// 判断点击的是 a
if (e.target.tagName === 'A') {
const n = e.target.offsetLeft
// 让 line 盒子来进行移动
line.style.transform = `translateX(${n}px)`
}
})
</script>
6. 电梯导航案例——综合案例(重点)
对于模块2 点击导航对应小模块,页面会跳转到对应大模块位置,同时小模块高亮(active类),
但需注意只涉及到导航中的前四个模块,不包含 顶部 这个小模块,所以在为其跳转及修改时,条件应该为 e.target.tagName === 'A' && e.target.dataset.name, 表示小模块同时还包含自定义属性name。
想要页面是滑动的效果,而不是直接跳转的,只需添加一句代码:
在css文件中 添加 html { scroll-behavior: smooth; },让滚动条丝滑滚动
模块三部分选择小盒子是使用属性选择器进行选择的,属性选择器 [属性=属性值] 属性值可加引号也可不加引号
<script>
// 可以将第一大模块(之前已经完成)部分放到自执行函数里面,防止变量污染
(function () {
// 第一大模块,页面滑动可以显示和隐藏
// 获取元素
const ele = document.querySelector('.xtx-elevator')
const entry = document.querySelector('.xtx_entry')
// console.log(ele);
// 给页面添加滚动事件
window.addEventListener('scroll', function () {
// 被卷去的头部大于entry 位置
const n = document.documentElement.scrollTop
ele.style.opacity = n >= entry.offsetTop ? 1 : 0
})
// 点击返回页面顶部
const backTop = document.querySelector('#backTop')
backTop.addEventListener('click', function(){
// document.documentElement.scrollTop = 0
// 或者
window.scrollTo(0, 0)
})
})();
// 第二第三部分都放到另外一个自执行函数里面
(function () {
// 2. 点击页面滑动
const elevatorList = document.querySelector('.xtx-elevator-list')
// console.log(elevatorList);
elevatorList.addEventListener('click', function(e){
// console.log(1);
if (e.target.tagName === 'A' && e.target.dataset.name) {
// 点击小模块,当前模块添加active 类
// 排他思想,先移除原来的类,再为当前元素添加active ,但此案例刚开始获取不到 active会报错
// 先获取这个类的元素
const old = document.querySelector('.xtx-elevator-list .active')
// console.log(old);
if (old) old.classList.remove('active')
// 当前元素添加active
e.target.classList.add('active')
// 获得自定义属性,获得的为字符串
// console.log(e.target.dataset.name);
// 根据小盒子的自定义属性值 去选择 对应的大盒子
const part = document.querySelector(`.xtx_goods_${e.target.dataset.name}`)
// console.log(part.offsetTop);
// 让页面滚动到对应的位置
document.documentElement.scrollTop = part.offsetTop
}
})
// 3.页面滚动,可以根据大盒子选 小盒子 添加 active类
window.addEventListener('scroll', function (){
// 3.1 先移除类
const old = document.querySelector('.xtx-elevator-list .active')
// console.log(old);
if (old) old.classList.remove('active')
// 3.2 判断页面当前滑动的位置,选择小盒子
// 获取四个大盒子,注意new为关键字,不能作为变量名
const news = document.querySelector('.xtx_goods_new')
const popular = document.querySelector('.xtx_goods_popular')
const brand = document.querySelector('.xtx_goods_brand')
const topic = document.querySelector('.xtx_goods_topic')
const footer = document.querySelector('.xtx_footer')
const n = document.documentElement.scrollTop
if (n >= news.offsetTop && n < popular.offsetTop) {
// 选择第一个小盒子
document.querySelector('[data-name=new]').classList.add('active')
} else if (n >= popular.offsetTop && n < brand.offsetTop ) {
// 选择第二个小盒子
document.querySelector('[data-name=popular]').classList.add('active')
} else if (n >= brand.offsetTop && n < topic.offsetTop ) {
// 选择第三个小盒子
document.querySelector('[data-name=brand]').classList.add('active')
} else if (n >= topic.offsetTop && n < footer.offsetTop ) {
// 选择第四个小盒子
document.querySelector('[data-name=topic]').classList.add('active')
}
})
})();
</script>