Web APIs---DOM- 事件高级

119 阅读3分钟

事件对象

事件对象是什么

​ 也是个对象,但是这个对象包含事件触发时的相关信息,例如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息

如何获取

​ 在事件绑定的回调函数的第一个参数就是事件对象,一般命名为event、ev、e

image-20220415235951729

部分常用属性

​ type:获取当前的事件类型

​ clientX/clientY:获取光标相对于浏览器可视窗口左上角的位置

​ offsetX/offsetY:获取光标相对于当前DOM/自身元素左上角的位置

​ key:用户按下的键盘键的值(现在不提倡使用keyCode)

事件流

事件流与两个阶段说明

​ 事件流指的是事件完整执行过程中的流动路径。简单来说:捕获阶段是从父到子 ,冒泡阶段是从子到父

image-20220415235900647

事件捕获和事件冒泡

捕获阶段

​ 从DOM的根元素开始去执行对应的事件,addEventListener第三个参数传入true代表是捕获阶段触发(一般很少使用)

a.addEventListener('click', function () {
            console.log('a');
        }, true); // 捕获

冒泡阶段

​ 当一个元素触发事件后,会依次向上调用所有父级元素的同名事件,事件冒泡是默认存在的

c.addEventListener('click',function () {
          console.log('c');
        },false) //冒泡  默认不用设置 

阻止事件流动

​ 因为默认就有冒泡模式的存在,所以容易导致事件影响到父级元素,若想把事件就限制在当前元素内,就需要阻止事件流动(需要拿到事件对象)

son.addEventListener('click',function (e) {
            console.log('son');
            // 阻止事件捕获和冒泡  影响父级
            e.stopPropagation()
        },

阻止默认行为

​ 阻止默认行为,比如a标签的点击跳转,form表单中button点击刷新行为

      
	   a.addEventListener("click",function (event) {
        console.log("a标签的点击触发啦");
        // 阻止a标签的默认行为,让他不要跳转
        event.preventDefault();
      })

       form.addEventListener("submit",function (event) {
         // 不要让页面再刷新
         event.preventDefault();
       })

       button.addEventListener("click",function (event) {
         event.preventDefault();  // 不要让页面再刷新
       })
常见的两种阻止默认行为
	 1 a标签的点击跳转
     2 form表单中button点击刷新行为
        1 阻止默认行为 - form表单 有一个 submit 事件 理解提交表单的触发-点击按钮的时候触发
        2 给button按钮绑定点击事件 也去阻止试试
        3 给button按钮 添加一个 type="button" 属性 
        4 换成 input标签 type="button"
        5 把button 移出form表单的区域 

事件委托

**原理:**当你想要给一组标签绑定事件实现业务时, 我们可以把事件绑定给父元素上 ,通过事件委托给父元素来做

优点:提高性能

实现:事件对象.target 可以获得真正触发事件的元素

<body>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
        <li>6</li>
    </ul>

    <script>

        const ul =document.querySelector('ul')

        ul.addEventListener('click',function (e) {
            // event.target 你当前点击的是哪个标签(点击最深最底层的那个标签)
            //  event.target 有可能是ul标签,有可能是li标签,还有可能是 a标签 在ul标签内元素都能触发
            e.target.style.color = 'red' // 太过笼统,不够具体,不够完美
        })
    </script>
</body>

指定标签

<body>
    <ul>
        <li>1 <a href="#"> 我是a1</a></li>
        <li>2 <a href="#"> 我是a2</a></li>
        <li>3 <a href="#"> 我是a3</a></li>
        <li>4 <a href="#"> 我是a4</a></li>
        <li>5 <a href="#"> 我是a5</a></li>
        <li>6 <a href="#"> 我是a6</a></li>
    </ul>
    <script>

    const ul = document.querySelector('ul')

    ul.addEventListener('click',function (e) {
        // e.target.nodeName === 'A' 当前点击的元素的标签名  大写字母
        if (e.target.nodeName === 'A') {
            e.target.style.color = 'pink' // 只有点击a标签才会触发
        }
    })
    </script>
</body>

综合案例---渲染学生信息案例

实现思路

image-20220415235816670

案例实现

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>08-综合案例-模版</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        a {
            text-decoration: none;
            color: #721c24;
        }

        h1 {
            text-align: center;
            color: #333;
            margin: 20px 0;
        }

        table {
            margin: 0 auto;
            width: 800px;
            border-collapse: collapse;
            color: #004085;
        }

        th {
            padding: 10px;
            background: #cfe5ff;

            font-size: 20px;
            font-weight: 400;
        }

        td,
        th {
            border: 1px solid #b8daff;
        }

        td {
            padding: 10px;
            color: #666;
            text-align: center;
            font-size: 16px;
        }

        tbody tr {
            background: #fff;
        }

        tbody tr:hover {
            background: #e1ecf8;
        }

        .info {
            width: 900px;
            margin: 50px auto;
            text-align: center;
        }

        .info input {
            width: 80px;
            height: 25px;
            outline: none;
            border-radius: 5px;
            border: 1px solid #b8daff;
            padding-left: 5px;
        }

        .info button {
            width: 60px;
            height: 25px;
            background-color: #004085;
            outline: none;
            border: 0;
            color: #fff;
            cursor: pointer;
            border-radius: 5px;
        }

        .info .age {
            width: 50px;
        }
    </style>
</head>

<body>
    <h1>新增学员</h1>
    <div class="info">
        姓名:<input type="text" class="uname" /> 年龄:<input type="text" class="age" />
        性别:
        <select name="gender" id="" class="gender">
            <option value="男"></option>
            <option value="女"></option>
        </select>
        薪资:<input type="text" class="salary" /> 就业城市:<select name="city" id="" class="city">
            <option value="北京">北京</option>
            <option value="上海">上海</option>
            <option value="广州">广州</option>
            <option value="深圳">深圳</option>
            <option value="曹县">曹县</option>
        </select>
        <button class="add">录入</button>
    </div>

    <h1>就业榜</h1>
    <table>
        <thead>
            <tr>
                <th>学号</th>
                <th>姓名</th>
                <th>年龄</th>
                <th>性别</th>
                <th>薪资</th>
                <th>就业城市</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
            <!-- <tr>
          <td>1</td>
          <td>这是名称</td>
          <td>这是年龄</td>
          <td>这是性别</td>
          <td>这是工资</td>
          <td>这是所在城市</td>
          <td>
            <a href="javascript:" class="del">删除</a>
          </td>
        </tr> -->
        </tbody>
    </table>
    <script>
        // 定义数组 负责存放表格要显示的数据
        let arr = []
        // 1.拼接字符串

        // 获取dom元素
        const tbody = document.querySelector('tbody')
        const add = document.querySelector('.add')
        const uname = document.querySelector('.uname')
        const age = document.querySelector('.age')
        const gender = document.querySelector('.gender')
        const salary = document.querySelector('.salary')
        const city = document.querySelector('.city')

        // 根据数组渲染页面
        getHtml()

        // 绑定添加按钮点击事件  实现数据的新增
        add.addEventListener('click', function () {
            // 声明一个对象来获取用户输入的值
            let user = {
                // 获取表单元素的值  点击事件生效获取
                stuId: arr.length > 0 ? arr[arr.length - 1].stuId + 1 : 1001,
                uname: uname.value,
                age: age.value,
                gender: gender.value,
                salary: salary.value,
                city: city.value,
            }
            // 2.将生成的对象添加到数组
            arr.push(user)
            // 当数组发生改变时  重新调用渲染页面的函数  省去了下面步骤
            getHtml()

            // let tr = document.createElement('tr')

            // tr.innerHTML = `
            //  <td>${user.stuId}</td>
            //  <td>${user.uname}</td>
            //  <td>${user.age}</td>
            //  <td>${user.gender}</td>
            //  <td>${user.salary}</td>
            //  <td>${user.city}</td>
            //  <td>
            //      <a href="javascript:" class="del">删除</a>
            //  </td>
            // `
			
            // 点击后恢复初始值
            Math.round(Math.random() * (1000 - 1) + 1),
            uname.value = ''
            age.value = ''
            gender.value = '男'
            salary.value = ''
            city.value = '北京'
        })

        // tbody绑定点击事件,同时判断被点击的是不是 del 删除标签
        tbody.addEventListener('click', function (e) {
            // 3.1 判断当前点击的是不是a标签 或者类名
             // 获取到a标签 上存放的 index
                // event.target =  a标签的dom元素
            if (event.target.nodeName === 'A') {
                // console.log(e.target);

                // <a data-index="2" href="javascript:" class="del">删除</a>
                // data-index="2" 自定义属性写法   固定搭配
                // dom.dataset.index(可以随意更改) 获取标签的自定义属性  方便后期事件触发了  获取之前存的数据,比如index

                const index = event.target.dataset.index;

                // 3.3 执行数组删除元素
                arr.splice(index, 1);

                // 数组发生改变  重新渲染页面
                getHtml()
            }
        })


        // 函数动态生成标签
        function getHtml() {
            let tbodyHtml = ''
            // 遍历数组
            for (let index = 0; index < arr.length; index++) {
                // 拼接字符串
                tbodyHtml += `
                        <tr>
                            <td>${arr[index].stuId}</td>
                            <td>${arr[index].uname}</td>
                            <td>${arr[index].age}</td>
                            <td>${arr[index].gender}</td>
                            <td>${arr[index].city}</td>
                            <td>${arr[index].salary}</td>
                            <td>
                                <a data-index="${index}" href="javascript:" class="del">删除</a>
                            </td>
                        </tr>`

            }
            tbody.innerHTML = tbodyHtml
        }
    </script>
</body>
</html>

拓展

forEach的使用

const arr = [43,523,6,865,1123,452,321]

        arr.forEach(function (value,index) {
            console.log(value,index); // 输出结果:value:43(值)  index:0(索引)
        })
forEach方法的使用:它可以遍历数组,要求传入一个回调函数
        语法:数组.forEach(function (value,index) {操作})
        value:代表当前遍历到的数组的元素/值
        index:当前元素/值所对应的索引
        注意:(function ()里面的两个值的顺序用于不能变,也不能少  
                如果遍历的是数据/数组,那么参数名称一般为value/v,index/i
                如果遍历的是元素伪数组,那么参数名称一般为ele/element
                不能在里面使用continue 会报错