web API day5

119 阅读5分钟

事件对象

  • 事件对象是什么?

也是个对象,这个对象里有事件触发时的相关信息。

例如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息.

  • 如何获取? 在事件绑定的回调函数的第一个参数就是事件对象。 一般命名为event、ev、e。
元素.addEventListener('click',function(事件对象){

})

<body>
    <button>1111111</button>
    <script>
        const btn = document.querySelector("button");
        // 事件对象 元素.addEventListener('click',function(事件对象);  事件对象一般命名为event、ev、e
       btn.addEventListener('click',function(event){
           console.log(event)
       })
    </script>
</body>

部分常用属性

属性说明
type获取当前的事件类型
clientX / clientY获取光标相对于浏览器可见窗口左上角的位置
offsetX / offsetY获取光标相对于当前DOM元素左上角的位置
key用户按下的键盘键的值。现在不提倡使用keyCode

示例:

  <body>
    <div>点击点击</div>
    <textarea name="" id="" cols="30" rows="10"></textarea>
    <script>
      // 获取按钮
      const btn = document.querySelector('div');
      //获取文本域
      const textarea = document.querySelector("textarea");
      

      btn.addEventListener('mousemove', function (event) {
        // console.log(event.type); // 输出当前的事件类型  少用
        // console.log(event.clientX,event.clientY ); // 返回 鼠标的位置-参照物 页面的左上角即可
        console.log(event.offsetX,event.offsetY);// 返回鼠标的坐标,参照物 是被点击的元素的左上角
      });

      //绑定键盘事件
      textarea.addEventListener("keydown",function(){
        console.log(event.key) //显示鼠标按下的键
      })
    </script>
  </body>

小鸟跟随鼠标移动案例

要求 :小鸟图标跟随着鼠标移动 。

<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>
        img {
            width: 50px;
            height: 50px;
            /* background-color: pink; */
            position: fixed;
            /* 移动自身宽度和高度的一半,让图片在鼠标指到的位置中心 */
            transform: translate(-50%, -50%);
        }

        body {
            /* 注意 body也是块级元素 没有设置高度的话 默认由内容撑开,所以给他加上高度是视口的100% */
            height: 100vh;
            /* 隐藏鼠标 */
            cursor: none;
        }
    </style>
</head>

<body>
    <!-- 要求 小鸟图标跟随着鼠标移动 -->
    <img src="./img/微信图片_20220411164226.png" alt="">

    <script>
        let img = document.querySelector("img");

        //鼠标在页面移动 绑定触发事件
        document.body.addEventListener('mousemove', function (event) {
            //修改div定位之后的位置调整 用clientX/clientY 套进去
            img.style.top = `${event.clientY}px`
            img.style.left = `${event.clientX}px`
        })
    </script>
</body>

微博发布案例-回车键发布

<body>
    <textarea name="" id="" cols="30" rows="10"></textarea>
    <button>发布</button>
    <ul>

    </ul>
    <script>
        let textarea = document.querySelector("textarea");
        let button = document.querySelector("button");
        let ul = document.querySelector("ul");

        button.addEventListener('click', function () {
            // 优化 :判断当前文本域的内容是不是空字符串,空字符串就发布不了
            //.trim() 获取到的是清除空格后的文本
            if (textarea.value.trim()==="") {
                return
            }
                let li = document.createElement('li');
                li.innerHTML = `${textarea.value}`;
                ul.appendChild(li);
                textarea.value = "";           
        })

        //绑定键盘按下事件  当键盘按回车 发布内容到li
        textarea.addEventListener("keydown", function (event) {
            if (event.key === "Enter") {
                // let li = document.createElement('li');
                // li.innerHTML = `${textarea.value}`;
                // ul.appendChild(li);
                // textarea.value = "";

                //  以上发布内容的代码可以优化 可以直接调用 发布的点击事件
                button.click();
            }
        })
    </script>
</body>

事件流

事件流指的是事件完整执行过程中的流动路径。

1649725348269

说明:假设页面里有个div,当触发事件时,会经历两个阶段,分别是捕获阶段冒泡阶段。 简单来说:捕获阶段是 从父到子 冒泡阶段是从子到父。

事件冒泡

概念:

  • 当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为事件冒泡。
  • 简单理解:当一个元素触发事件后,会依次向上调用所有父级元素的同名事件 事件冒泡是默认存在的。
  • js默认冒泡事件:addEventListener("click",function(){},false) ;

事件捕获

概念:

  • 从DOM的根元素开始去执行对应的事件 (从外到里)。

  • 事件捕获需要写对应代码才能看到效果。

    说明:

    • addEventListener第三个参数传入true代表是捕获阶段触发(很少使用)。
    • 若传入false代表冒泡阶段触发,默认就是false
    • 若是用 L0 事件监听,则只有冒泡阶段,没有捕获
  • addEventListener("click",function(){},true), 谁加了 true,那他的点击事件会优先触发

<body>
    <div class="one">a
        <div class="two">b
            <div class="three">c</div>
        </div>
    </div>

    <script>
        //事件流动分为两个阶段:
        //1.捕获阶段 是 父节点 流动到 子节点
        //2.冒泡阶段 是 子节点 流动到 父节点

        //我们可以修改触发事件 让他选择使用捕获阶段还是冒泡阶段
        //addEventListener 可以选择使用冒泡还是捕获
        //写法:addEventListener(事件类型,事件处理函数,捕获还是冒泡(默认值false,可以省略)
        //addEventListener("click",function(){},true), 谁加了 true,那他的点击事件会优先触发

        const a = document.querySelector(".one")
        const b = document.querySelector(".two")
        const c = document.querySelector(".three")

        a.addEventListener("click", function () {
            console.log(a)
        }, true) //true 会优先执行该点击事件

        b.addEventListener("click", function () {
            console.log(b)
        })//默认是false,可以省略不写

        c.addEventListener("click", function () {
            console.log(c)
        })
    </script>
</body>

阻止冒泡

在事件对象中 event 找到一个方法 停止冒泡 event.stopPropagation();

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

4.此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效。

语法:

事件对象. event.stopImmediatePropagation();

示例:

    <script>
        let num = document.querySelector(".num")
        const a = document.querySelector(".one")
        const b = document.querySelector(".two")
        const c = document.querySelector(".three")
        num.innerText =1;

        a.addEventListener("click", function () {
            num.style.backgroundColor= 'aqua';
            num.innerText = +num.innerText+1;
        }, ) 

        b.addEventListener("click", function () {
            num.style.backgroundColor= 'pink';
            num.innerText = +num.innerText + 10;
            //阻止事件冒泡
            event.stopImmediatePropagation();
        })

        c.addEventListener("click", function (event) {
            num.style.backgroundColor= 'blueviolet';
            num.innerText = +num.innerText + 100;
            //阻止事件冒泡
            event.stopImmediatePropagation();
        })
    </script>
</body>

鼠标经过事件: mouseover 和 mouseout 会有冒泡效果 mouseenter 和 mouseleave 没有冒泡效果(推荐)

阻止标签默认行为

阻止默认行为,比如链接点击不跳转,表单域的不提交。

语法:

语法.event.preventDefault()

清除表单和超链接跳转默认样式示例:

<body>
    <a href="https://www.baidu.com/">百度</a>
    <form action="">
        <button type="button">点击按钮 会自动刷新</button>
        <!--input 标签 type= “button”    不会自动刷新  -->
        <input type="button"> 
    </form>
    <script>
        //event.preventDefault();阻止标签默认样式

        const a = document.querySelector("a")
        const button = document.querySelector("button")
        const form =document.querySelector("form")

        /* 
        1. a标签的点击跳转
        2.form 表单中的button 点击刷新行为
           1.阻止默认行为 :form表单 有一个submit事件,理解提交表单的触发。
           2.给 button绑定点击事件 阻止
           3.给button 添加个 type=“button” 属性
           4.换成 input 标签 type= “button”
           5.把button 移出form表单区域
        */

        //阻止a点击跳转功能
        a.addEventListener('click', function (event) {
            event.preventDefault();
            console.log(11111)
        })

        //阻止按钮点击刷新功能 1
        // form.addEventListener("submit", function (enevt) {
        //     event.preventDefault();  
        // })

        
        //阻止按钮点击刷新功能 2
        // button.addEventListener('click', function (event) {
        //     event.preventDefault();
        // })
    </script>
</body>

鼠标右键自定义菜单-案例

<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>
        body{
            height: 100vh;
        }
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        ul {
            width: 150px;
            height: 200px;
            list-style: none;
            text-align: center;
            line-height: 50px;
            border: 1px solid #999;
            display: none;
            position: fixed;
        }

        li {
            height: 50px;
            border-bottom: 1px solid #999;
        }

        li:hover {
            background-color: skyblue;
            color: #fff;
            /* 鼠标光标变手指 */
            cursor: pointer; 
        }
    </style>
</head>

<body>
    <ul>
        <li>添加图片</li>
        <li>切换壁纸</li>
        <li>下载壁纸</li>
        <li>设置</li>
    </ul>

    <script>
        let ul = document.querySelector("ul");

        //1.给页面绑定鼠标右键按下事件
        document.body.addEventListener('contextmenu', function (event) {
            //清除页面鼠标默认样式跳出来的
        event.preventDefault();
        // 定义两个变量是鼠标移动的坐标  获取的坐标是相对于浏览器可见窗口左上角的位置
        const left = event.clientX;
        const top = event.clientY;

        //ul标签鼠标右键按下 显示,及固定定位的位置,把上面获取到的位置套进去就行,因为获取到的只是数字,没有单位,记得加px,
        ul.style.display = 'block';
        ul.style.left = left + 'px';
        ul.style.top = top + 'px';
      });

      //2.再给页面绑定鼠标左键按下时 ul标签消失
      document.body.addEventListener('click',function(){
          ul.style.display='none'
      })
    </script>
</body>

事件委托

**事件委托 **是利用事件流的特征解决一些开发需求的知识技巧。

总结:

  • 优点:给父级元素加事件(可以提高性能)。
  • 原理:事件委托其实是利用事件冒泡的特点, 给父元素添加事件,子元素可以触发。
  • 实现:事件对象.target 可以获得真正触发事件的元素。

1649732682195

示例:

<body>
    <ul>
        <li>1</li>
        <li>1</li>
        <li>1</li>
        <li>1</li>
        <li>1</li>
    </ul>

    <script>
        let ul = document.querySelector("ul");

        ul.addEventListener("click",function(event){
            //直接这样做不完美,因为点ul也会变红
            // event.target.style.backgroundColor="red";

            //只有点击li标签才触发
            //event.target.nodeName  显示当前点击元素的标签名字,大写的
            //要求只有鼠标点到的位置 标签名是li  他的颜色才变红。
            if(event.target.nodeName==="LI"){
                event.target.style.backgroundColor="red";
            }
           
        })
    </script>
</body>

录入学员信息-综合案例

<!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>综合案例</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>
      // 1.1 定义数组 负责存放表格要显示的数据
      let arr = [ ];
      const tbody = document.querySelector('tbody');
      // 2  给 录入绑定点击事件
      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');

      // 1.2 根据数组渲染页面
      renderTableByArr();

      // 2  录入按钮绑定点击事件
      add.addEventListener('click', function () {
        // 2.1 创建一个新的对象 把表单数据都合并到对象中
        const data = {
          // 学号
          id: Date.now(),
          // 姓名
          uname: uname.value,
          // 年龄
          age: age.value,
          // 性别
          gender: gender.value,
          // 薪资
          salary: salary.value,
          // 就业城市
          city: city.value,
        };
        // 2.2 给数组插入新的元素
        arr.push(data);

        // 2.3 数组发生改变  重新调用渲染页面的函数
        renderTableByArr();

        // 2.4 表单数据清空
        uname.value = '';
        age.value = '';
        gender.value = '男';
        salary.value = '';
        city.value = '北京';
      });

      // 3 tbody绑定点击事件,同时判断被点击的是不是 del 删除标签
      tbody.addEventListener('click', function (event) {
        // 3.1 判断当前点击的是不是a标签 (a标签就是删除的标签)
        if (event.target.nodeName === 'A') {
          // <a data-index="2" href="javascript:" class="del">删除</a>

          // 获取到a标签 上存放的 index
          // event.target =  a标签的dom元素
          // console.dir(event.target.dataset.index)
          const index = event.target.dataset.index;

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

          // 3.4 调用根据数组渲染页面的函数 
          renderTableByArr();
        }
      });
        
      // 根据数组渲染表格
      function renderTableByArr() {
        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>
         `;
        }

        // 把生成的tr插入到 tbody中
        tbody.innerHTML = html;
      }
    </script>
  </body>
</html>

滚动事件

滚动事件:当页面进行滚动时触发的事件。

  • 很多网页需要检测用户把页面滚动到某个区域后做一些处理, 比如固定导航栏,比如返回顶部。

  • 事件名:scroll 监听整个页面滚动: 1649750594937

    给 window 或 document 添加 scroll 事件。 监听某个元素的内部滚动直接给某个元素加即可。

滚动的距离

这个代码可以获取当前页面滚动的距离:

document.documentElement.scrollTop

示例:

    <script>
        window.addEventListener("scroll",function(){
            //这个代码可以获取当前页面滚动的距离
            console.log(document.documentElement.scrollTop)
        })
    </script>

固定导航案例

<!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;
        }
        header{
            height: 250px;
            background-color: aqua;
        }

        nav{
            height: 250px;
            background-color: blueviolet;
            
        }

        
        .fixed{
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
        }

        div{
            background-color: pink;
        }
    </style>
</head>
<body>
    <header></header>
    <nav ></nav>
    <div>
        <ul>
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
            <li>5</li>
            <li>6</li>
            <li>7</li>
            <li>8</li>
            <li>9</li>
            <li>10</li>
            <li>11</li>
            <li>12</li>
            <li>13</li>
            <li>14</li>
            <li>15</li>
            <li>16</li>
            <li>17</li>
            <li>18</li>
            <li>19</li>
            <li>20</li>
            <li>21</li>
            <li>22</li>
            <li>23</li>
            <li>24</li>
            <li>25</li>
            <li>26</li>
            <li>27</li>
            <li>28</li>
            <li>29</li>
            <li>30</li>
            <li>31</li>
            <li>32</li>
            <li>33</li>
            <li>34</li>
            <li>35</li>
            <li>36</li>
            <li>37</li>
            <li>38</li>
            <li>39</li>
            <li>40</li>
            <li>41</li>
            <li>42</li>
            <li>43</li>
            <li>44</li>
            <li>45</li>
            <li>46</li>
            <li>47</li>
            <li>48</li>
            <li>49</li>
            <li>50</li>

        </ul>
    </div>

    <script>
        // 要求:鼠标滑动到导航栏的时候 导航栏固定定位在顶部


        // 获取 导航栏 和 头部
        const nav =document.querySelector("nav")
        const header =document.querySelector("header");

        //给窗口绑定鼠标滚动事件
        window.addEventListener("scroll",function(event){
            //定义一个 代表是鼠标滚动的位置
            const scrollTop=document.documentElement.scrollTop;
            //当滚动位置过了头部的时候,相当于过了头部的高度时
            if(scrollTop>=250){
                //给导航栏加个类名, 这个类名是css原先就设置好的固定定位样式等
               nav.classList.add('fixed');
               //给头部加个下外边距是自己的高度   因为导航固定定位的时候脱标了,会挡住下面的内容,给头部设置着下边距的距离 把内容挤下去显示。
               header.style.marginBottom=250+'px';
            } else{
                //未满足上面条件时,导航栏的定位标签 移除掉 以及 头部的下边距为0
                nav.classList.remove('fixed');
               header.style.marginBottom=0;
            }

        })
    </script>
</body>
</html>

css的方式完成以上案例

在导航标签加上粘性定位 即可:

 position: sticky;

存在兼容性问题 慎用!

主动设置页面的滚动距离示例:

 <body>
    <button>设置页面滚动距离 200</button>
    <header></header>
    <nav></nav>
    <div>
      <h1>1</h1>
      <h1>2</h1>
      <h1>3</h1>
      <h1>4</h1>
      <h1>5</h1>
      <h1>6</h1>
      <h1>7</h1>
      <h1>8</h1>
      <h1>9</h1>
      <h1>10</h1>
      <h1>11</h1>
      <h1>12</h1>
      <h1>13</h1>
      <h1>14</h1>
      <h1>15</h1>
      <h1>16</h1>
      <h1>17</h1>
      <h1>18</h1>
      <h1>19</h1>
      <h1>20</h1>
      <h1>21</h1>
      <h1>22</h1>
      <h1>23</h1>
      <h1>24</h1>
      <h1>25</h1>
      <h1>26</h1>
      <h1>27</h1>
      <h1>28</h1>
      <h1>29</h1>
      <h1>30</h1>
      <h1>31</h1>
      <h1>32</h1>
      <h1>33</h1>
      <h1>34</h1>
      <h1>35</h1>
      <h1>36</h1>
      <h1>37</h1>
      <h1>38</h1>
      <h1>39</h1>
      <h1>40</h1>
      <h1>41</h1>
      <h1>42</h1>
      <h1>43</h1>
      <h1>44</h1>
      <h1>45</h1>
      <h1>46</h1>
      <h1>47</h1>
      <h1>48</h1>
      <h1>49</h1>
      <h1>50</h1>
      <h1>51</h1>
      <h1>52</h1>
      <h1>53</h1>
      <h1>54</h1>
      <h1>55</h1>
      <h1>56</h1>
      <h1>57</h1>
      <h1>58</h1>
      <h1>59</h1>
      <h1>60</h1>
      <h1>61</h1>
      <h1>62</h1>
      <h1>63</h1>
      <h1>64</h1>
      <h1>65</h1>
      <h1>66</h1>
      <h1>67</h1>
      <h1>68</h1>
      <h1>69</h1>
      <h1>70</h1>
      <h1>71</h1>
      <h1>72</h1>
      <h1>73</h1>
      <h1>74</h1>
      <h1>75</h1>
      <h1>76</h1>
      <h1>77</h1>
      <h1>78</h1>
      <h1>79</h1>
      <h1>80</h1>
      <h1>81</h1>
      <h1>82</h1>
      <h1>83</h1>
      <h1>84</h1>
      <h1>85</h1>
      <h1>86</h1>
      <h1>87</h1>
      <h1>88</h1>
      <h1>89</h1>
      <h1>90</h1>
      <h1>91</h1>
      <h1>92</h1>
      <h1>93</h1>
      <h1>94</h1>
      <h1>95</h1>
      <h1>96</h1>
      <h1>97</h1>
      <h1>98</h1>
      <h1>99</h1>
      <h1>100</h1>
    </div>

    <script>
      const button = document.querySelector('button');
      //给按钮加点击事件
      button.addEventListener('click', function () {
        // 设置页面的滚动距离
        document.documentElement.scrollTop = 200;
      });
    </script>
  </body>