DOM-事件基础

本文深入介绍了JavaScript中的事件监听,包括DOM L0和DOM L2的事件监听方式,以及事件类型如焦点、文本输入和全选等。通过实例展示了如何实现淘宝搜索框、微博输入计数、全选文本框和购物车加减操作。此外,还探讨了高阶函数、环境变量this的使用,以及如何运用排他思想实现Tab栏切换。案例丰富,代码详实,帮助读者掌握JavaScript事件处理的核心技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、事件

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,不要有空格。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值