一、事件
1、事件监听
(1)事件概念
事件是在编程时系统内发生的动作或者发生的事情
比如用户在网页上单击一个按钮
(2)事件监听的概念
就是让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为注册事件
- 语法:
- 事件监听三要素:
事件源: 哪个dom元素被事件触发了,要获取dom元素
事件: 用什么方式触发,比如鼠标单击 click、鼠标经过 mouseover 等
事件调用的函数: 要做什么事
<body>
<button>点击</button>
<script>
let btn = document.querySelector('button')
btn.addEventListener('click',function(){
alert('恭喜你')
})
</script>
</body>
事件类型要加引号;
函数是点击之后再去执行,每次点击都会执行一次
案例–淘宝点击关闭二维码
需求:点击x关闭之后,淘宝二维码关闭
分析:
①:点击的是关闭按钮
②:关闭的是父盒子
核心:利用样式的显示和隐藏完成, display:none 隐藏元素 display:block 显示元素
<!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>
.box{
display: flex;
width: 160px;
height: 160px;
margin: 100px auto;
}
.box img{
border: 1px solid #ccc;
}
.box i{
width: 10px;
height: 10px;
border: 1px solid #ccc;
line-height: 7px;
text-align: center;
color: #ccc;
cursor: pointer;
}
</style>
</head>
<body>
<div class="box">
<i>x</i>
<img src="./images2/code.png" alt="">
</div>
<script>
//获取元素
let i = document.querySelector('i')
let box = document.querySelector('.box')
//事件监听
i.addEventListener('click',function(){
//关闭->隐藏display:none
box.style.display = 'none'
})
</script>
</body>
</html>
案例–随机点名
需求:点击按钮之后,随机显示一个名字,抽到的人从名单中划掉,抽完则禁用按钮
分析:
①:点击的是按钮
②:随机抽取一个名字
③:当名字抽取完毕,则利用 disabled 设置为 true
<!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>
div{
width: 200px;
height: 30px;
border: 1px solid pink;
text-align: center;
line-height: 30px;
}
</style>
</head>
<body>
<div></div>
<button >点击随即点名</button>
<script>
let arr=['赵云', '黄忠', '关羽', '张飞', '马超', '刘备', '曹操', 'pink老师']
//获取元素
let btn = document.querySelector('button')
let div = document.querySelector('div')
//随机函数
function getRamdon(x,y){
return Math.floor(Math.random()*(y-x+1)+x)
}
//事件监听
btn.addEventListener('click',function(){
let r = getRamdon(0,arr.length-1)
div.innerHTML = arr[r]
//抽中就删除
arr.splice(r,1)
//没人了就不让抽了
if(arr.length===0){
btn.disabled = true
btn.innerHTML = '已经抽完'
}
})
</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>
h2{
text-align: center;
}
.box{
display: flex;
align-items: center;
margin: 50px auto;
width: 600px;
font-size: 25px;
}
.box p {
color: red;
}
.btn{
text-align: center;
}
.btn button{
width: 120px;
height: 35px;
margin: 0 50px;
}
</style>
</head>
<body>
<h2>随机点名</h2>
<div class="box">
<span>名字是:</span>
<p>这里显示名字</p>
</div>
<div class="btn">
<button class="start">开始</button>
<button class="end">结束</button>
</div>
<script>
let arr=['赵云', '黄忠', '关羽', '张飞', '马超', '刘备', '曹操', 'pink老师']
//获取元素
let start = document.querySelector('.start')
let end = document.querySelector('.end')
let txt = document.querySelector('p')
//因为timer是全局变量,如果在start监听函数中定义,end监听函数中访问不到这个局部变量
let timer = 0
//因为r如果定义在start监听函数中,end监听函数中访问不到这个变量
let r = 0
//随机函数
function getRamdon(x,y){
return Math.floor(Math.random()*(y-x+1)+x)
}
//事件监听
start.addEventListener('click',function(){
//随机函数抽取,快速不断抽取,定时器
timer = setInterval(function(){
// 注意这句要放进定时器,否则就会发生一直都是同一个名字在快速抽取
r = getRamdon(0,arr.length-1)
txt.innerHTML = arr[r]
},25)
})
end.addEventListener('click',function(){
//停止定时器
clearInterval(timer)
arr.splice(r,1)
if (arr.length === 0){
start.disabled = true
end.disabled = true
}
})
</script>
</body>
</html>
二、拓展阅读-事件监听版本
- DOM L0
事件源.on事件 = function() { }
- DOM L2 (现在经常用的)
事件源.addEventListener(事件, 事件处理函数)
发展史:
DOM L0 :是 DOM 的发展的第一个版本; L:level
DOM L1:DOM级别1 于1998年10月1日成为W3C推荐标准
DOM L2:使用addEventListener注册事件
DOM L3: DOM3级事件模块在DOM2级事件的基础上重新定义了这些事件,也添加了一些新事件类型
三、事件类型
- 焦点事件(表单获得光标):如小米搜索框,有光标的时候框变色并提示搜索内容,光标移开恢复原样
- 文本事件(表单输入触发):根据输入的不同提示不同产品
案例–小米搜索框
需求:当表单得到焦点,显示下拉菜单,失去焦点隐藏下来菜单
分析:
①:开始下拉菜单要进行隐藏
②:表单获得焦点 focus,则显示下拉菜单,并且文本框变色(添加类)
③:表单失去焦点,反向操作
<!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;
}
ul{
list-style: none;
}
a{
text-decoration: none;
}
.box{
width: 223px;
margin: 100px auto;
}
.box input{
width: 223px;
height: 48px;
border: 1px solid #e0e0e0;
padding-left: 10px;
font-size: 14px;
outline:none ;
/* 加个过渡,更高级一点 */
transition: all 0.3s;
}
/* 获得焦点的时候直接添加类使得文本框颜色变化 */
.box .search{
border: 1px solid #ff6700;
}
.box ul{
/* 一开始下拉框不显示 */
display: none;
width: 223px;
border: 1px solid #ff6700;
border-top: 0;
}
.box ul li{
width: 223px;
height: 28px;
}
ul li a{
display:block;
padding: 6px 15px;
font-size: 12px;
color: #424242;
}
li:hover{
background-color: #eee;
}
</style>
</head>
<body>
<div class="box">
<!-- type='search'语义好,input专门用来做搜索的 -->
<input type="search" placeholder="小米笔记本">
<ul>
<li><a href="#">全部商品</a></li>
<li><a href="#">小米11</a></li>
<li><a href="#">小米10S</a></li>
<li><a href="#">小米笔记本</a></li>
<li><a href="#">小米手机</a></li>
<li><a href="#">黑鲨4</a></li>
<li><a href="#">空调</a></li>
</ul>
</div>
<script>
//获取元素
let input = document.querySelector(`input`)
let ul = document.querySelector('ul')
//事件响应,获得焦点
input.addEventListener('focus',function(){
// 显示下拉菜单,注意block需要加引号,否则会把block当成没有定义的变量,报错
ul.style.display = 'block'
//文本框变色
input.classList.add('search')
//或者input.style.border = '1px solid #ff6700'
})
// 事件监听,失去焦点事件
input.addEventListener('blur',function(){
ul.style.display = 'none'
input.classList.remove('search')
})
</script>
</body>
</html>
案例–微博输入
需求:用户输入文字,可以计算用户输入的字数
分析:
①:判断用输入事件 input
②:不断取得文本框里面的字符长度
③:把获得数字给下面文本框
<!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;
}
.wei{
width:900px;
margin: 0 auto;
}
.wei textarea{
width: 900px;
height: 112px;
resize: none;
border-radius: 10px;
outline: none;
padding-top: 10px;
padding-left: 20px;
font-size: 18px;
}
.wei .bottom{
float: right;
}
.wei span{
color: #666;
}
.wei .use{
color: red;
}
.wei button{
width: 100px;
height: 30px;
background-color: rgb(0, 132, 255);
border: 0;
line-height: 30px;
text-align: center;
color: #fff;
font:bold 14px '宋体';
cursor: pointer;
}
button:hover{
background: rgb(0, 225, 255);
}
</style>
</head>
<body>
<div class="wei">
<img src="./images3/tip.png" alt="">
<br>
<!-- maxlength控制最大输入长度 -->
<textarea placeholder="说点什么吧..." id="area" cols="30" rows="10" maxlength="200"></textarea>
<div class="bottom">
<span class="use">0</span>
<span>/</span>
<span>200</span>
<button>发布</button>
</div>
</div>
<script>
// 获取元素
let text = document.querySelector('textarea')
let use = document.querySelector('.use')
// 事件监听,输入出发监听
text.addEventListener('input',function(){
//不断获得文本框的字符长度,表单数据获取需要通过元素的value获取,而对于div则需要通过innerHTML获取
use.innerHTML = text.value.length
})
</script>
</body>
</html>
案例–全选文本框案例1
需求:用户点击全选,则下面复选框全部选择,取消全选则全部取消,文字对应变化
分析:
①:全选复选框点击, checked === true,全选取消点击,checked === false
②:把下面所有的小复选框状态checked,改为和全选复选框一致
③:如果当前处于全选状态,则把文字改为取消, 否则反之
<!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;
}
table{
width: 500px;
margin: 100px auto;
border-collapse: collapse;
text-align: center;
}
table tr:first-child{
background-color: #09c;
height: 25px;
line-height: 25px;
}
th{
font: bold 16px "微软雅黑";
color: #fff
}
td{
border: 1px solid #d0d0d0;
color: #404060;
padding: 10px;
}
.all{
margin-right: 5px;
vertical-align: middle;
}
</style>
</head>
<body>
<table>
<tr>
<th>
<input type="checkbox" class="all" name="" id=""><span>全选</span>
</th>
<th>商品</th>
<th>商家</th>
<th>价格</th>
</tr>
<tr>
<td>
<input type="checkbox" class="one" name="" id="">
</td>
<td>小米手机</td>
<td>小米</td>
<td>¥1999</td>
</tr>
<tr>
<td>
<input type="checkbox" class="one" name="" id="">
</td>
<td>小米净水器</td>
<td>小米</td>
<td>¥4999</td>
</tr>
<tr>
<td>
<input type="checkbox" class="one" name="" id="">
</td>
<td>小米电视</td>
<td>小米</td>
<td>¥5999</td>
</tr>
</table>
<script>
//获取元素
let all = document.querySelector('.all')
let one = document.querySelectorAll('.one')
let span = document.querySelector('span')
//事件监听,全选按钮
all.addEventListener('click',function(){
//当全选按钮点击时,下面的按钮的状态和他一致,不能直接这样 one.checked = all.Checked,
//因为querySelectorAll取出来的是一个数组,不能直接给里面的东西赋值,要循环取出再赋值
for (let i = 0; i< one.length; i++){
one[i].checked = all.checked;
}
//如果当前处于选中状态,则把文字改为取消, 否则反之
if (all.checked){
span.innerHTML = '取消'
}
else{
span.innerHTML = '全选'
}
})
</script>
</body>
</html>
存在缺陷:若单独点满下面所有的复选框,全选也会✔,若全选了之后下面有一个取消了,全选也会取消,针对案例1完善----->全选文本框案例2
案例–全选文本框案例2
需求:用户点击全选,则下面复选框全部选择,取消全选则全部取消,文字对应变化
+用户将下面每个都选中,全选默认选中,在都选了时,只要有一个取消,全选也要取消,文字对应变化
分析:
①:遍历下面的所有的小选项,添加点击事件(每个小的都要添加事件响应的,用循环更快、操作方便)
②:在事件内部,遍历所有的小选项状态,只要有一个为false 就将全选状态设置为false , 把文字改
为全选,并且直接return (退出循环)
③:在循环结束(下面小选项没有一个没勾选,checked全为true)将全选的状态直接设置为true,文字改为取消
<!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;
}
table{
width: 500px;
margin: 100px auto;
border-collapse: collapse;
text-align: center;
}
table tr:first-child{
background-color: #09c;
height: 25px;
line-height: 25px;
}
th{
font: bold 16px "微软雅黑";
color: #fff
}
td{
border: 1px solid #d0d0d0;
color: #404060;
padding: 10px;
}
.all{
margin-right: 5px;
vertical-align: middle;
}
</style>
</head>
<body>
<table>
<tr>
<th>
<input type="checkbox" class="all" name="" id=""><span>全选</span>
</th>
<th>商品</th>
<th>商家</th>
<th>价格</th>
</tr>
<tr>
<td>
<input type="checkbox" class="one" name="" id="">
</td>
<td>小米手机</td>
<td>小米</td>
<td>¥1999</td>
</tr>
<tr>
<td>
<input type="checkbox" class="one" name="" id="">
</td>
<td>小米净水器</td>
<td>小米</td>
<td>¥4999</td>
</tr>
<tr>
<td>
<input type="checkbox" class="one" name="" id="">
</td>
<td>小米电视</td>
<td>小米</td>
<td>¥5999</td>
</tr>
</table>
<script>
//1.获取元素
let all = document.querySelector('.all')
let one = document.querySelectorAll('.one')
let span = document.querySelector('span')
//2.事件监听,全选按钮
all.addEventListener('click',function(){
//当全选按钮点击时,下面的按钮的状态和他一致,不能直接这样 one.checked = all.Checked,
//因为querySelectorAll取出来的是一个数组,不能直接给里面的东西赋值,要循环取出再赋值
for (let i = 0; i< one.length; i++){
one[i].checked = all.checked;
}
//如果当前处于选中状态,则把文字改为取消, 否则反之
if (all.checked){
span.innerHTML = '取消'
}
else{
span.innerHTML = '全选'
}
})
// 3. 小按钮监听,每个小按钮都要监听, 同时给多个元素绑定相同事件,for循环
for (let i = 0; i < one.length; i++){
one[i].addEventListener('click',function(){
// 只要点击任何一个小按钮,都要遍历所有的小按钮
for (let j = 0; j < one.length ; j++){
// 看看是不是有小按钮没有选中
if(one[j].checked ===false){
// 如果有false 则退出循环 结束函数
all.checked = false
span.innerHTML = '全选'
//只要下面有一个没勾选,即使这个勾选了当前的one[i]也不能全选,不必每个判断,
//只要遇到一个没选,就能让全选不选了,直接退出函数function()
return
}
}
//勾选小按钮one[i]后,遍历发现全部的one都勾选了,此时全选也要勾选,并改文字
all.checked = true
span.innerHTML = '取消'
})
}
</script>
</body>
</html>
案例–购物车加减操作
需求:用户点击加号,则文本框+1,点击减号,则文本框-1,如果文本框为1,则禁用减
分析:
①:给添加按钮注册点击事件, 获取表单的value,然后自增
②:解除减号的disabled状态
③:给减号按钮添加点击事件,获取表单的value,然后自减
④:自减结束需要判断,如果结果小于等于1 则添加上disabled状态
<!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>
*{
box-sizing: border-box;
}
.box{
display: flex;
}
input{
width: 50px;
height: 44px;
text-align: center;
margin-right: 0;
border: 1px solid #ccc;
outline: none;
}
.btn{
display: flex;
flex-direction: column;
}
button{
width: 24px;
height: 22px;
border: 1px solid #ccc;
border-radius: 0;
}
</style>
</head>
<body>
<div class="box">
<!-- readonly只读 -->
<input type="text" value="1" readonly>
<div class="btn">
<button class="plus">+</button>
<button class="minus" disabled>-</button>
</div>
</div>
<script>
// 获取元素
let plus = document.querySelector('.plus')
let minus = document.querySelector('.minus')
let input = document.querySelector('input')
//事件监听
plus.addEventListener('click',function(){
input.value ++
minus.disabled = false
})
minus.addEventListener('click',function(){
input.value --
//表单取过来是字符串类型
if(+input.value === 1){
minus.disabled = true
}
})
</script>
</body>
</html>
二、高阶函数
高阶函数可以被简单理解为函数的高级应用,JavaScript 中函数可以被当成【值】来对待,基于这个特性实现函数的高级应用。
【值】就是 JavaScript 中的数据,如数值、字符串、布尔、对象等。
-
函数表达式:将函数当成一个值一样传给变量
函数表达式必须要先声明再调用 -
回调函数:如果将函数 A 做为参数传递给函数 B 时,我们称函数 A 为回调函数
fn是回调函数
function()是回调函数
三、环境变量
环境对象指的是函数内部特殊的变量 this ,它代表着当前函数运行时所处的环境
作用:弄清楚this的指向,可以让我们代码更简洁
函数的调用方式不同,this 指代的对象也不同
【谁调用, this 就是谁】 是判断 this 指向的粗略规则
this指代btn
直接调用函数,其实相当于是 window.函数,所以 this 指代 window
fn()是省略的函数调用写法,完整是window.fn()
四、编程思想
排他思想:只有当前元素为A状态,其他元素为B状态
- 使用:
✔ 干掉所有人:使用for循环
✔ 复活他自己:通过this或者下标找到自己或者对应的元素
想要实现五个按钮中,点哪个哪个变粉红色,其他的不变色
//使用干掉所有人(for循环)+复活我自己思路:
<!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>
.pink{
background-color: pink;
}
</style>
</head>
<body>
<button>第1个</button><button>第2个</button><button>第3个</button><button>第4个</button><button>第5个</button>
<script>
//获取元素
let btn = document.querySelectorAll('button')
//事件监听
for (let i = 0; i <btn.length ; i++ ){
btn[i].addEventListener('click',function(){
//干掉所有人
for(let j = 0; j<btn.length ; j++){
btn[j].classList.remove('pink')
}
//复活我自己,btn[i]添加事件监听,this指代btn[i]
this.classList.add('pink')
})
}
</script>
</body>
</html>
上述方法可行,但是有点复杂,每次点击一个按钮,都要将所有按钮遍历一遍,取消他们的颜色,下面方法采用:
点击按钮2时,找到之前点击的按钮1,取消其粉色,新点击的按钮2加上粉色
点击按钮3时,再找到按钮2,取消其粉色,给3加上粉色
……
<!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>
.pink{
background-color: pink;
}
</style>
</head>
<body>
<button class="pink">第1个</button><button>第2个</button><button>第3个</button><button>第4个</button><button>第5个</button>
<script>
//获取元素
let btn = document.querySelectorAll('button')
//事件监听
for (let i = 0; i <btn.length ; i++ ){
btn[i].addEventListener('click',function(){
//去粉上一个,但是第一个点击的按钮之前没有粉色按钮,会报错
//工作中会有一个按钮一开始有就有默认粉色
document.querySelector('.pink').classList.remove('pink')
//加粉我自己,btn[i]添加事件监听,this指代btn[i]
this.classList.add('pink')
})
}
</script>
</body>
</html>
五、综合案例–Tab栏切换
需求:点击不同的选项卡,底部可以显示不同的内容
分析:
①:点击当前选项卡,当前添加类,其余的兄弟移除类, 排他思想
②:下面模块盒子全部隐藏,当前的模块显示
<!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>
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
ul{
list-style: none;
}
a{
text-decoration: none;
}
img{
width: 100%;
}
/* 头部tab */
.wrapper{
width: 1000px;
margin: 100px auto;
}
.wrapper ul{
display: flex;
width: 320px;
height: 37px;
border: 1px solid #ddd;
border-bottom: 0;
}
.wrapper ul li{
width: 80px;
padding:6px 0;
text-align: center;
border-top: 4px solid #fff;
cursor: pointer;
}
.wrapper ul span{
display: inline-block;
color:#ddd;
font-size: 14px;
margin-top: 11px;
}
/* 商品内容 */
.wrapper .product{
height: 474px;
border: 1px solid #ddd;
}
.wrapper .product .main{
display: none;
}
/* 头部tab栏被点击的有红色上边框 */
.wrapper ul .active{
border-top: 4px solid red;
}
/* 对应的商品模块显示 */
.wrapper .product .active{
display: block;
}
</style>
</head>
<body>
<div class="wrapper">
<ul>
<li class="item active">国际大牌</li><span>|</span>
<li class="item">国妆名牌</li><span>|</span>
<li class="item">清洁用品</li><span>|</span>
<li class="item">男士精品</li>
</ul>
<div class="product">
<div class="main active"><a href="#"><img src="./imgs/guojidapai.jpg" alt=""></a></div>
<div class="main"><a href="#"><img src="./imgs/guozhuangmingpin.jpg" alt=""></a></div>
<div class="main"><a href="#"><img src="./imgs/qingjieyongpin.jpg" alt=""></a></div>
<div class="main"><a href="#"><img src="./imgs/nanshijingpin.jpg" alt=""></a></div>
</div>
</div>
<script>
//获取元素
let item = document.querySelectorAll('.item')
let main = document.querySelectorAll('.main')
//事件监听
for (let i=0 ;i<item.length ; i++){
item[i].addEventListener('click',function(){
// 头部tab栏切换
//注意:querySelector('')里面如果是类选择器要加. 但是classList.remove/add('')中不用,
//因为classList已经表明是类了
document.querySelector('.item.active').classList.remove('active')
this.classList.add('active')
// 底部显示隐藏模块
document.querySelector('.main.active').classList.remove('active')
main[i].classList.add('active')
})
}
</script>
</body>
</html>
注意①
// 头部tab栏切换
document.querySelector('.item.active').classList.remove('active')
this.classList.add('active')
一开始觉得头部tab栏切换的后面两个括号:classList.remove('active')
和add('active')
中不应该只写active
,
因为.active
类有两个,分别是.wrapper ul .active
;.wrapper .product .active
如下:
/* 头部tab栏被点击的有红色上边框 */
.wrapper ul .active{
border-top: 4px solid red;
}
/* 对应的商品模块显示 */
.wrapper .product .active{
display: block;
}
写成classList.remove('ul active')
, add('product active')
,然后报错,最后发现只需要写active就行,因为比如
<ul>
<li class="item active">国际大牌</li><span>|</span>
<li class="item">国妆名牌</li><span>|</span>
<li class="item">清洁用品</li><span>|</span>
<li class="item">男士精品</li>
</ul>
document.querySelector('.item.active').classList.remove('active')
后就是
<li class="item">国际大牌</li><span>|</span>
直接找到<li class="item active">
去除active
类;
又如this.classList.add('active')
后就是<li class="item active">国妆名牌</li><span>|</span>
,给item[i]
加上active
类的时候,上面两个.active
都有层次,.wrapper .product .active
显然不在item[i]路径里面,.wrapper ul .active
与item的路径一致(item在ul中)。
如果写成 add('ul active')
就会变成<li class="item ul active">国妆名牌</li><span>|</span>
,报错
注意②
如果是嵌套的盒子,如div里面套ul,就是 div ul,但如果是并列的交集,如 <li class="item active">国际大牌</li><span>|</span>
,想找到.active
并且不想和别的.active
混淆,可以写成.item.active
,不要有空格。