web API 第四天 (+第五天补充 事件流 事件委托)

174 阅读2分钟

知识补充- let 和 const

1649663323709

作用

​ 在程序设计时,一些数据永远不会被更改,优先用const(不小心发现被修改,程序就报错,有利于解决)

​ 能用const就用const,不能用const就用let

​ 永远不用var

区别

​ 1.普通类型的数据 直接写 = 表示修改数据 报错

​ 2.复杂类型的数据 直接写 = 表示修改 报错 (如果arr.push不会报错。等于号才报错)

1649672298431

​ 3.复杂类型的数据 写= 相当于重新开辟新空间 报错

总结

​ 1.cosnt和let一样都可以声明变量

​ 2.const 声明的变量不能修改 let 可以随意修改

​ 3.判断是不是修改 直接看有没有 写= 或者自增自减

​ 4.能用const 就不用let

1649664545214

DOM-事件高级

事件对象

本质

​ 1.事件对象也是一个对象,这个对象装的是当我们触发事件时的相关信息

​ 2.例如:点击事件中,时间存放了鼠标点在哪个位置等信息

语法

1649665155848

常用属性

1.type

​ 获取当前事件类型

2.clientX、clientY

​ 获取光标相对于浏览器窗口左上角位置(元素移动还是参照浏览器)

3.offsetX、offsetY

​ 获取光标相对于当前DOM元素左上角位置(参照自身元素位置)

4.key

​ 用户按下的键盘值

移动案例

1649667723633

<script>
        let img = document.querySelector(`img`)
        document.addEventListener(`mousemove`,function(e){
            const left = e.clientX
            const top = e.clientY
            img.style.left = left+`px`
            img.style.top = top+`px`
        })
</script>

思路

​ 1.主要在于client属性获取的是X,Y数字

2.联想定位letf,top

​ 3.把属性值给图片的定位值

回车案例

1649681432339


    <script>
        let are = document.querySelector(`.are`)
        let btn = document.querySelector(`button`)
        let ul = document.querySelector(`ul`)

        btn.addEventListener(`click`,function(){
            if(are.value.trim()===``){
                return //返回不再执行
            }

            if(are.value.length!==0){
                let html = `<li>${are.value}</li>`
            
                ul.innerHTML += html

                are.value=``
            }

        })

        document.addEventListener(`keydown`,function(e){
            

            if(e.key===`Enter`){
                btn.click()
            }
            
           e.preventDefault()//阻止浏览器标签默认行为 阻止a跳转行为
        })
    </script>
</body>
</html>

思路

​ 1.主要在回车发布,给整个body添加按下事件

​ 2.判断当只有e.key是回车时,才执行代码 要加``

​ 3.两个额外知识点要注意

事件流(了解)

本质:事件流值的是事件执行过程的流动1649725498357

代码举例

<body>
    <div class="a"><div class="b"><div class="c"></div>
        </div>
    </div>
    <script>
        const a = document.querySelector(`.a`)
        a.addEventListener(`click`,function(){
            console.log(a);
        },false)//默认,冒泡阶段
        const b = document.querySelector(`.b`)
        b.addEventListener(`click`,function(){
            console.log(b);
        },true)// 捕获阶段
        const c = document.querySelector(`.c`)
        c.addEventListener(`click`,function(){
            console.log(c);
        },false)
    </script>
</body>

理解

​ 1.本质这里就是给多个嵌套的父子结构绑定点击事件,如果点击了子元素,就产生了事件流动

​ 2.事件流动分为两个阶段(1.捕获阶段;2.冒泡阶段(默认))

​ 3.就像跳水一样 :

1649725632303

​ 4.可以修改触发事件,选择捕获还是冒泡(默认是冒泡)

​ addEventlistener(事件类型,函数,捕获还是冒泡(默认是false,可以省略))

​ addEventlistener ("click",function(){},true)这就是修改为捕获阶段

总结:了解特点,之后开发过程默认使用冒泡阶段。

小案例:点击上面嵌套盒子,点谁显示谁颜色

<script>
        let p = document.querySelector(`p`)
        const a = document.querySelector(`.a`)
        a.addEventListener(`click`,function(){
        p.style.backgroundColor = `red`
        },true)
        const b = document.querySelector(`.b`)
        b.addEventListener(`click`,function(){
            p.style.backgroundColor = `pink`

        },true)
        const c = document.querySelector(`.c`)
        c.addEventListener(`click`,function(){
            p.style.backgroundColor = `aqua`

        },true)
</script>

问题延伸:如果换成数字相加,发现此做法不行,不能点谁加谁,数字会叠加父元素数字,还是会触发父元素。因为事件时间捕获和冒泡阶段。

阻止冒泡(解决方式)

本质:默认存在的冒泡,会导致事件影响到父元素

作用:若要把事件执行限制在当前元素内,就要阻止事件流动

语法

1649729648207

问题延伸解决方案

<script>
        let p = document.querySelector(`p`)
        const a = document.querySelector(`.a`)
        a.addEventListener(`click`,function(e){
            p.style.backgroundColor = `red`
            p.innerText = +(p.innerText)+1
            e.stopPropagation()
            console.log(a);
        })

        const b = document.querySelector(`.b`)
        b.addEventListener(`click`,function(e){
            p.style.backgroundColor = `pink`
            p.innerText = +(p.innerText)+10
            e.stopPropagation()
            console.log(b);


        })
        const c = document.querySelector(`.c`)
        c.addEventListener(`click`,function(e){
            p.style.backgroundColor = `aqua`
            p.innerText = +(p.innerText)+100
            // 阻止事件流动
            e.stopPropagation()
            
</script>

阻止默认行为

本质:让标签默认行为不执行,如a标签跳转

语法

1649729742886

代码举例

 <script>
        const form = document.querySelector(`form`)
        const button = document.querySelector(`button`)
        const a = document.querySelector(`a`)

        a.addEventListener(`click`,function(e){
            e.preventDefault()//阻止默认行为 跳转
        })

        form.addEventListener(`submit`,function(e){
            e.preventDefault()//不让页面刷新
        })

        button.addEventListener(`click`,function(e){
            e.preventDefault()//不让页面刷新
        })
</script>

右键重新设置案例

<script>
        let ul = document.querySelector(`ul`)
        document.addEventListener(`contextmenu`,function(e){
            e.preventDefault()

            ul.style.display = `block`
            let left = e.clientX+`px`
            let top = e.clientY+`px`
            ul.style.left = left
            ul.style.top = top
        })

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

思路

​ 1.首先写静态结构,写出一个想要的结构

​ 2.给body添加右键事件,阻止右键默认行为 也就是右键弹出的页面

​ 3.把想要的结构用之前的跟随移动案例 把新的结构给右键点击事件

​ 4.给body添加点击事件,点击就消息页面

事件委托

本质:事件委托是利用事件流的特征(捕获冒泡),解决开发需求

作用:给父元素加事件,之前都是给每个子元素遍历绑定,更加高效。

语法:事件对象.target 表示当前事件触发的是哪个标签(触发时的最底层标签,依据事件流特点!!!

之前获取LI点击事件做法

<script>
        let li = document.querySelectorAll(`li`)
        for (let index = 0; index < li.length; index++) {
            li[index].addEventListener(`click`,function(){
                li[index].style.backgroundColor=`red`
            })
            
        }
</script>

现在获取做法:

<script>
        let ul = document.querySelector(`ul`)
        ul.addEventListener(`click`,function(e){
            //事件委托,把本来要遍历li绑定的事件 绑定父元素上 实现
            //点哪个元素,就获取哪个(最底层)
            e.target.style.backgroundColor=`red`
            //不过这样做,可能获取ul,li,a 不够完美
        })
</script>

优化做法:(只要点击li)

<script>
        let ul = document.querySelector(`ul`)
            if(e.target.nodeName===`LI`){
                e.target.style.backgroundColor=`red`
            }
        })
</script>

总结

​ 1.把事件委托给父元素

​ 2.用target触发

​ 3.如果想要只点击LI才触发 用判断配合nodeName(获取标签,大写)

综合案例

1649757322875

<script>
      
      let arr = [
        // {id:`1`,uname:`黄某`,age:`18`,gender:`男`,salary:`200`,city:`广州`}
      ]
      let name = document.querySelector(`.uname`)
      let age = document.querySelector(`.age`)
      let sex = document.querySelector(`.gender`)
      let money = document.querySelector(`.salary`)
      let city = document.querySelector(`.city`)

      let btn = document.querySelector(`.add`)
      let tbody = document.querySelector(`tbody`)
      
      rander()
      btn.addEventListener(`click`,function(){
        const  date = {
          id:Date.now(),
          uname:name.value,
          age:age.value,
          gender:sex.value,
          salary:money.value,
          city:city.value
        }
        arr.push(date)

        rander()
      })

      tbody.addEventListener(`click`,function(event){
        if(event.target.nodeName===`A`){
          const index = event.target.dataset.index
          arr.splice(index,1)

          rander()
        }
      })

      function rander() {
        let html = ``
        for (let index = 0; index < arr.length; index++) {
          html += `<tr>
          <td>${arr[index].id}</td>
          <td>${arr[index].uname}</td>
          <td>${arr[index].age}</td>
          <td>${arr[index].gender}</td>
          <td>${arr[index].salary}</td>
          <td>${arr[index].city}</td>
          <td>
            <a data-index="${index}" href="javascript:" class="del">删除</a>
          </td>
        </tr>`
          
        }
        
        return  tbody.innerHTML =html
      }
</script>

解题思路

​ 1.创建一个对象数组,存放数据(数据驱动视图!!!)

​ 2.封装渲染函数,提取对象数组中的值

​ 3.点击了发布,把插入内容整合成一个对象,把对象插入外边大的数组对象中,放入封装好的渲染函数。

​ 4.点击删除,运用事件委托,给父元素声明点击事件,用e.target判断只有标签A才可以点击。

​ 5.如何删除,思考要是存在下标,那我点谁就获取哪个下标然后可以删除谁。

​ 6.在渲染函数的删除标签上添加data-index=“${index}”,dir一下e.target发现在这个对象中的dataset有一个下标,和数组一样。点击谁就获取递增的下标

​ 7.将下标值赋予一个变量,用splice(index,1)点击就删除

总结:多做多思考,尽量通过思考而不是肌肉记忆