webAPI (04) 学习分享

78 阅读4分钟

web API (04)

事件对象

获取事件对象

  • 事件对象是什么
    1. 也是个对象,这个对象里有事件触发时的相关信息
    2. 列如: 鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息
  • 获取
    1. 在事件绑定的回调函数的第一个参数就是事件对象
    2. 一般命名为 event 、 e 、 ev
  <script>
        const bnt = document.querySelector('button')
        bnt.addEventListener('click',function (event) {
            console.log(event);  // 存放事件触发一瞬间的信息  - 鼠标位置信息
        })
    </script>

事件对象常用属性

  • 部分常用属性
    • type
      1. 获取当前的事件类型
    • clientX / clientY
      1. 获取光标相对于浏览器可见窗口左上角的位置
    • offsetX / offsetY
      1. 获取光标相对于当前Dom元素左上角的位置
  <script>
        const div = document.querySelector('div')
                                // 鼠标移动动
        div.addEventListener('mousemove',function (event) {
            // console.log(event.type);   // 输出当前的事件类型  少用
            // console.log(event.clientX,event.clientY); // 反回 鼠标的位置 - 参照物 页面的左上角即
            console.log(event.offsetX,event.offsetY);  // 返回鼠标的坐标, 参照物 是被点击的元素的左上角
        })
    </script>

跟随鼠标移动案例

  • 需求:一张图片一直跟着鼠标移动

    分析:

    ①:鼠标在页面中移动,用到 mousemove 事件

    ②:不断把鼠标在页面中的坐标位置给图片left和top值即可

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no"
    />
    <title>04-小鸟跟随鼠标.html</title>
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      /* div {
        width: 100px;
        height: 100px;
        background-color: aqua;
        position: fixed;
      } */
      img {
        position: fixed;
        /* width: 50px; */
        /* 移动自身宽度和高度的一半 */
        transform: translate(-50%, -50%);
      }
      body {
        height: 100vh;
        /* 隐藏鼠标 */
        cursor: none;
      }
    </style>
  </head>
  <body>
    <h1>用户鼠标不要移动那么快</h1>
    <!-- <div></div> -->
    <img src="./images/xn.png" alt="" />
    <script>
      /* 
      1 给body标签 绑定 鼠标移动事件  
        body也是一个普通的块级元素 高度由内容撑开 同时 div使用了定位-脱标 body标签没有高度 
      2 事件触发了 获取 事件对象的坐标 clientX 
      3 把坐标设置给div的left top
       */

      // const div = document.querySelector('div');
      const img = document.querySelector('img');
      document.body.addEventListener('mousemove', function (event) {
        const left = event.clientX;
        const top = event.clientY;

        img.style.left = left + 'px';
        img.style.top = top + 'px';
      });
    </script>
  </body>
</html>

键盘案键


    <script>
      // 给body标签 绑定 键盘按下事件 keydown
      document.body.addEventListener('keydown', function (event) {
        console.log(event.key);// 当下按下的按键 ! 
      });
    </script>


案例

  • 需求:按下回车键盘,可以发布信息

    分析:

    ①:用到按下键盘事件 keydown 或者 keyup 都可以

    ②:如果用户按下的是回车键盘,则发布信息

    ③:按下键盘发布新闻,其实和点击发布按钮效果一致 send.click()

<!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>
  </head>
  <body>
    <textarea id="ttx"></textarea>
    <button>发布</button>
    <ul></ul>
    <script>
      let ttx = document.querySelector('#ttx')
      let bnt = document.querySelector('button')
      let ul  = document.querySelector('ul')
      // 给按钮标签设置点击事件
      bnt.addEventListener('click',function () {
          // 点击发布的时候添加一个li标签
          let li = document.createElement('li')
          // 让文本的内容等于 li 里面的内容
          li.innerText = ttx.value
          ul.appendChild(li)
          // 点击发布的时候 文本里面的内容等于空字符串
          ttx.value = ''
      })
      document.body .addEventListener('keydown',function (event) {
        console.log(event.key);
        // 给按钮绑定过点击事件,点击事件也是可以主动触发
        if(event.key === 'Enter'){
            bnt.click()// 相当于你点击了一下按钮
        }
      })
    </script>
  </body>
</html>

事件流

事件流和两个阶段说明

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

1649820488730.png

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

事件捕获和冒泡

  • 事件流动

    1. 给多个父子结构的标签绑定事件,先点击了子元素,产生事件流动

    2. 事件流动 分成了两个阶段

      1. 捕获阶段 父节点 流动到子节点
      2. 冒泡节点 子节点 流动到父节点 默认
      3. 事件流动方向 默认是 使用了冒泡 - 点击儿子标签 触发 儿子 - 父亲 - 爷爷
    3. 我们可以修改触发事件 让它选择使用 捕获阶段还是冒泡阶段

      • addEventListener 可以选择使用冒泡还是捕获

      • addEventListener事件类型 ,事件处理函数,捕获还是冒泡默认值 false,可以省略))

        <script>
            const b = document.querySelector('.box')
                b.addEventListener('click',function () {
                    console.log('b');
                },true) // 捕获
        </script>
        
    4. 总结

      1. 捕获和冒泡 特点 了解
      2. 默认情况 冒泡 如果想要修改 可以 addEventListener 第三个参数传入 true 即可
      3. 以后代码开发过程中, 还是继续使用默认的 冒泡阶段

阻止冒泡

  • 在事件对象中 event 找到一个方法 停止冒泡 event.stopPropagation();
  b2.addEventListener("click", function (event) {
        console.log("b2");
        p.innerText = +(p.innerText) +100
        p.style.backgroundColor = 'blue'
        // 阻止冒泡
        event.stopPropagation()

      },true);

阻止标签的默认行为

 <body>
    <a href="http://www.baidu.com">百度</a>

    <form >
      <!-- <button type="button">点击我 就会自动刷新</button> -->
      <!-- <input type="button" value="点击我"> -->
    </form>
    <button>刷新</button>
    <script>
      /* 
      1 a标签的点击跳转
      2 form表单中button点击刷新行为
        1 阻止默认行为 - form表单 有一个 submit 事件 理解提交表单的触发-点击按钮的时候触发
        2 给button按钮绑定点击事件 也去阻止试试
        3 给button按钮 添加一个 type="button" 属性 
        4 换成 input标签 type="button"
        5 把button 移出form表单的区域 

      使用新技术 阻止标签默认行为 
       */
      const a=document.querySelector("a");
      const form=document.querySelector("form");
      const button=document.querySelector("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();  // 不要让页面再刷新
      // })
    </script>

事件委托感受

  • 优点 : 给父级元素加事件(可以提高性能)
  • 原理 : 事件委托其实是利用事件冒泡的特点 ,给父元素添加事件,子元素可以触发
  • 实现 : 事件对象 . target 可以获得真正触发事件的元素
 <script>
      // 事件委托
      //  本来想要给li标签绑定事件实现业务
      //  把事件绑定写在 父元素上  把li标签应该要做的事情 委托给父元素来做! 
      const ul=document.querySelector("ul");
      ul.addEventListener("click",function (event) {
        //  event.target 有可能是ul标签,有可能是li标签,还有可能是 a标签 
        // 一会再来解决这个问题。
        event.target.style.backgroundColor="red";// 不够完美的
        // event.target 你当前点击的是哪个标签(点击最深最底层的那个标签即可)
        // console.log(event.target);// 获取到被点击的li标签 
      })
    </script>

事件委托-nodeName

 <script>
      const ul = document.querySelector('ul');
      ul.addEventListener('click', function (event) {
        // event.target.style.backgroundColor="red";
        // console.log(event.target);

        // 只有点击了li标签才触发
        // console.log(event.target.nodeName);// 当前点击的元素的标签名 大写
        if (event.target.nodeName === 'LI') {
          console.log('改变颜色');
          event.target.style.backgroundColor = 'red';
        }
      });
    </script>

案例

1649822601350.png

<!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 = [];
      let 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");
      getHtml();
      // 根据渲染页面

      // 按钮绑定点击事件
      add.addEventListener("click", function () {
        // 创建一个新的对象  把表单数据都合并到对象中
        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 数组发生改变  重新调用渲染页面的函数
        getHtml();
        //2.4 表单数据清空
        uname.value = "";
        age.value = "";
        gender.value = "男";
        salary.value = "";
        city.value = "广州";
      });
      // 3 tbody 绑定点击事件,同时判断被点击的是不是  del 删除标签
      tbody.addEventListener("click", function (event) {
        // 判断当前点击的是不是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.num;

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

          // 3.4 调用根据数组渲染页面的函数
          getHtml();
        }
      });
      function getHtml() {
        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-num href="javascript:" class="del">删除</a>
          </td>
        </tr>`;
        }
        // 把生成的tr插入到tbody 中
        tbody.innerHTML = html;
      }
    </script>
  </body>
</html>

滚动事件和加载事件

滚动事件

  • 当页面滚动时触发的事件
  • 很多网页需要加测用户把页面滚动到某个区域后做一些处理,比如固定导航栏,返回顶部
  • 事件名 : scroll
    <script>
        const div= document.querySelector('div')
        //设置滚动事件
        div.addEventListener('scroll',function () {
            console.log('你在滚动');
        })
    </script>

当前滚动距离

  • 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: 200px;
        background-color: yellow;
      }

      nav {
        height: 200px;
        background-color: blue;
      }
      .flex{
          position: fixed;
          top: 0px;
          left: 0px;
          width: 100%;
      }

      div {
        background-color: aqua;
      }
      body {
        height: 100vh;
      }
    </style>
  </head>
  <body>
    <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>
          /*
      需求:  当页面滚动到一定的高度  nav变成了固定定位
      1 一定高度 ???   其实就是header标签的高  250px

      步骤:
      1 需要在页面滚动距离 大于或者等于 250 的高时候
        1 设置nav标签做一个 固定定位
      2 否则就取消固定定位

      3 小bug 因为 nav标签做固定定位,不再拥有高度,自然把下面的标签给挡住!!!
        解决它
        给nav上面的标签 header标签 添加下外边距,大小 等于 nav的高
       */
      const nav = document.querySelector('nav')
      const header = document.querySelector('header')
      window.addEventListener('scroll',function () {
          const num = document.documentElement.scrollTop
          if (num>=200) {
              nav.classList.add('flex')
              header.style.marginBottom = 200 + 'px'

              
          }else{
              nav.classList.remove('flex')
              header.style.marginBottom = 0
          }
      })
    </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>
      body {
        height: 8000px;
        background-image: linear-gradient(red, blue);
      }
      div {
        /* background-color: yellow; */
        position: fixed;
        bottom: 20px;
        right: 0px;
        display: none;
      }
      a {
        background-image: url(./04-小火箭/images/gotop.png);
        width: 150px;
        height: 195px;
        display: inline-block;
      }
      a:hover {
        background-image: url("./04-小火箭/images/gotop.gif");
      }
    </style>
  </head>
  <body>
    <div class="xxx">
      <a href="javascript:;">
        <!-- <img src="./04-小火箭/images/gotop.png" alt="" /> -->
      </a>
    </div>
    <script>
      const div = document.querySelector("div");
      const a = document.querySelector("a");
      window.addEventListener("scroll", function () {
        const num = document.documentElement.scrollTop;
        if (num >= 1000) {
          div.style.display = "block";
        } else {
          div.style.display = "none";
        }
      });
      a.addEventListener("click", function () {
        let xxx = setInterval(function () {
          let xo =document.documentElement.scrollTop -= 200;
            console.log(xo);
          if ((document.documentElement.scrollTop === 0)) {
              console.log('你好呀');
            clearInterval(xxx);
          }
        }, 100);
      });
    </script>
  </body>
</html>