web API 第二天 -事件(+第三天补充 环境对象+排他)

146 阅读3分钟

DOM-事件基础

事件

​ 本质:事件是在编程系统内发生的动作或者说是发生的事情

​ 例如:我点了一下按键,我把鼠标移入了某个地方 都叫做事件

事件监听

​ 作用:让程序检测是否有事件发生,根据发生的事件做出响应 也叫注册事件

​ 语法:元素.addEventListener("事件",要执行的函数)

1649042856158.png

事件三要素

​ 事件源:那个DOM元素要事件触发? 先获取DOM

​ 事件:用什么方式触发,鼠标点击click 鼠标经过mouseover等

​ 调用函数:当事件触发,做什么样的行为?

1649043071794.png

<script>
        let btn = document.querySelector(`button`)
        btn.addEventListener(`click`,function(){
            console.log(`开摆`)
        })

        let div =document.querySelector(`div`)
        div.addEventListener(`mouseover`,function(){
            console.log(`快进来`)
        })
</script>

注意点

​ 1.事件类型要加引号

​ 2.函数是事件发生之后再去执行,每触发一次事件,函数就执行一次

点击数字案例

<script>
        let btn = document.querySelector(`button`)
        let index = 1000
        btn.addEventListener(`click`,function(){
            // btn.innerText -= 7 第一种

            // ++btn.innerText  OK  ++ -- 会做隐式转换
            // btn.innerText += 1 不OK 数据类型是字符串不会隐式转换 

            // 第三种
            index-- 
            index -=6
            btn.innerText = `(${index})`
            
            if (index===-1){
                alert(`没了,别点了`)
            }
        })
</script>

点击隐藏案例

<body>
    <div>
        <img src="./image/pic01.jpg" alt="">
    </div>

    <script>
        let div = document.querySelector(`div`)

        div.addEventListener(`click`,function(){
            div.style.display = `none`
        })
    </script>
</body>

点击-随机点名案例(重要)


<script>
        let h1 = document.querySelector(`h1`)
        let but = document.querySelector(`button`)
        let but1 = document.querySelector(`.button1`)
        let arr = [`刘备`,`关羽`,`张飞`,`赵云`,`黄盖`,`黄忠`]

        let timer //先是一个空篮子


        // 定时器疯狂点击,疯狂开启多个定时器
            /* 节流!!! (让我们程序一个一个一次一次执行 不要同时执行多个)
                在一个定时器没有执行结束的时候 不能开启另外一个定时器 */
        but.addEventListener(`click`,function(){
            //在教timer的空篮子放了东西
        timer= setInterval(function(){
            /* 优化:
             1.数组放里面,每跑一次就执行一次 用let都占据内存空间,所以放到外边
            2.如果定时器业务多,可以提取出去封装  
            
            
            这里如何解决:
            1.开启定时器 就禁用 不给你点击
            2.清除定时器 就启用
            
            1.在每一次开启定时器之前 都停止一次定时器*/
            let index = Math.round( Math.random()*(arr.length-1) )
            h1.innerHTML=arr[index]
        },68)

        but.disabled = true
        but1.disabled = false
        })
       
        but1.addEventListener(`click`,function(){
            //清除timer 篮子里的东西
            clearInterval(timer)

        but1.disabled = true
        but.disabled = false
        })
</script>

我的初步思路

​ 1.首先想到数组配合随机数

​ 2.想到定时器

​ 3.套上事件

​ 总结:虽然做出,可是没有总体结构,思路尚不清晰 只是根据需求一步一步从上到下

优化点

​ 1.疯狂点击定时器,会疯狂生成定时器。引出节流知识点(让我们程序一个一个一次一次执行 不要同时执行多个)

解决方法

​ 点击就禁用按钮 .disable

​ 在定时器最开始添加清除定时器 (实现原理)

1649057580389.png

​ 2.把index随机值封装函数

优化后代码:

<script>
        let h1 = document.querySelector(`h1`)
        let but = document.querySelector(`button`)
        let but1 = document.querySelector(`.but`)
        let arr = [`刘备`,`关羽`,`张飞`,`赵云`,`黄盖`,`黄忠`]
        let timeId

        // 封装了随机index的函数
        function geiRandom() {
            let index = Math.round( Math.random()*(arr.length-1) )
                h1.innerText = arr[index]
        }

        but.addEventListener(`click`,function(){
            //一开始是undefined 所以来个判断 优雅!
            if(timeId!==undefined){clearInterval(timeId)} 
            // 把封装函数拿进来,注意是函数,不是调用函数
            timeId=setInterval(geiRandom,100)
        })

        but1.addEventListener(`click`,function(){
            clearInterval(timeId) 
        })
</script>

老师思路:

​ 1.不是从上到下一口气

​ 2.而是从大体结构开始入手,分别测试功能

​ 3.再在两个按钮中

点击-表单全选案例 (重要)

我的初步代码

<script>
        let fick = document.querySelector(`#checkAll`)
        let check = document.querySelector(`.ck`)
        let check1 = document.querySelector(`.ck1`)
        let check2 = document.querySelector(`.ck2`)
       
        fick.addEventListener(`click`,function(){
            if(fick.checked != false){
            check.checked = true
            check1.checked = true
            check2.checked = true
            }else if (fick.checked != true) {
            check.checked = false
            check1.checked = false
            check2.checked = false
            }
            
        })
</script>

解题思路

​ 1.获取多个对面

​ 2.监听事件

​ 3.根据需求写 发现当全选框勾选时,我取消勾选框,也会全选

​ 4.加条件判断

缺点:太不优雅,太低级

老师初步代码

<script>
        let fick = document.querySelector(`#checkAll`)
        let check = document.querySelector(`.ck`)
        let check1 = document.querySelector(`.ck1`)
        let check2 = document.querySelector(`.ck2`)
       
        fick.addEventListener(`click`,function(){
            check.checked=fick.checked 
            check1.checked=fick.checked 
            check2.checked=fick.checked 
        })

</script>

解题思路

​ 直接让列表中要选中的等于全选框选中的

缺点:当列表多,每一个都获取一下,麻烦,不优雅

老师优化后代码

<script>
        let fick = document.querySelector(`#checkAll`)
        let checkAll = document.querySelectorAll(`.ck`)
        

        fick.addEventListener(`click`,function(){

            for (let index = 0; index < checkAll.length; index++) {
                checkAll[index].checked = fick.checked
            }
        })

        // 老师最终思路,用数组配合循环,不管有多少列表,都能一步到位
</script>

优化案例

思考:如何实现当单选框全选时,全选框自动选上。取消一个单选框,全选框自动取消

6731a4c9e15c6aa872c44e376e9f86b.png

<script>
        let ck = document.querySelectorAll(`.ck`)
        let checkAll = document.querySelector(`#checkAll`)  

        checkAll.addEventListener(`click`,function(){
            for (let index = 0; index < ck.length; index++) {
                ck[index].checked=checkAll.checked
            }
        })


        for (let index = 0; index < ck.length; index++) {
            ck[index].addEventListener(`click`,function(){
                let checked = geic()
                checkAll.checked = checked
            }) 
        }

        function geic() {    
            let num = 0
            for (let index = 0; index < ck.length; index++) {
                
                if(ck[index].checked){
                    num++
                }
  
            }

            if(num === ck.length){
                return true
            }else {
                return false
            }
        } 
</script>

思路

​ 1.给每一个单独的复选框绑定点击事件

​ 2.什么时候需要让 全选 选中 /每一个都选择

​ 什么时候需要让 全选 不选中/只要一个没选中

实现

​ 1.定义一个变量 就是选择的商品数量

​ 一开始 num = 0

​ 2.开始对商品循环

​ 3.判断每一个商品选择状态

​ 如果选择,让num++

​ 4.循环结束 判断num 是不是和商品数组长度相同

​ 相同就是全选上了 返回true

​ 不相同 就是没有达到 返回false

最后整合代码

<script>
        let ck = document.querySelectorAll(`.ck`)
        let checkAll = document.querySelector(`#checkAll`)  

        checkAll.addEventListener(`click`,function(){
            for (let index = 0; index < ck.length; index++) {
                ck[index].checked=checkAll.checked
            }
        })


        for (let index = 0; index < ck.length; index++) {
            ck[index].addEventListener(`click`,function(){
                let checked = geic()
                checkAll.checked = checked
            }) 
        }

        function geic() {    
            let num = 0
            for (let index = 0; index < ck.length; index++) {
                
                if(ck[index].checked){
                    num++
                }
  
            }

            if(num === ck.length){
                return true
            }else {
                return false
            }
        } 
</script>

环境对象

​ 本质:环境对象指的是函数内部特殊的变量this

作用与细节

弄清楚this的方向,能让代码简洁

​ 1.在前端的JS中,全局变量可以理解为windows的一个属性

1649215083002.png

​ 2.谁调用,this就是谁

<script>
        function show() {
            console.log(this);
        }
        show()//输出windows

        let huangmou = {
            name:`黄某`,
            function () {
                console.log(this)
            }
        }

       huangmou.function()  //输出huangmou对象

</script>

​ 3.小补充

1649216368530.png

编程思想

排他思想

​ 本质:当前元素为A状态,其他为B状态

使用

1.干掉所有

​ 使用for循环

2.复活自己

​ 通过this或下标找到自己或者对应的元素

1649214250736.png

<script>
        let li = document.querySelectorAll(`li`)
        
        // 第一种做法
         for (let index = 0; index < li.length; index++) {
            li[index].addEventListener(`click`,function(){
                
                for (let index = 0; index < li.length; index++) {
                    li[index].classList.remove(`color`)
                }

                this.classList.add(`color`)
            })
        } 

        // 第二种做法
        for (let index = 0; index < li.length; index++) {
            li[index].addEventListener(`click`,function(){

                // 把所有标签干成白色
                for (let index = 0; index < li.length; index++) {
                    li[index].style.backgroundColor = `#fff`
                    
                }
                // 给自己加红色  
                this.style.backgroundColor = `red`
            })
            
        }
</script>

综合案例

1649216992407.png

<script>
      let lis =document.querySelectorAll(`li`)
      let divs = document.querySelectorAll(`.products .main`)
      

      for (let index = 0; index < lis.length; index++) {
        lis[index].addEventListener(`click`,function(){


          for (let index = 0; index < lis.length; index++) {
            lis[index].classList.remove(`active`)
          }
          this.classList.add(`active`)

          for (let index = 0; index < divs.length; index++) {
            divs[index].classList.remove(`active`)
          }
          divs[index].classList.add(`active`)

          
        })
      }     
</script>

解题思路

​ 1.确认点击事件

​ 2.获取对象,循环遍历点击事件

​ 3.排他思想的运用