Web APIs(六)

61 阅读5分钟

webAPI

一、事件流

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

2.说明:完整执行过程中的流动路径会经历两个阶段,分别是捕获阶段、冒泡阶段

(捕获阶段是 从父到子 冒泡阶段是从子到父)

3.事件冒泡

①当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为事件冒泡

②简单理解:当一个元素触发事件后,会依次向上调用所有父级元素的同名事件

4.事件捕获

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

②语法

DOM.addEventListener(事件类型,事件处理函数,是否使用捕获机制)
// addEventListener第三个参数传入true代表是捕获阶段触发(很少使用)
// 若传入false代表冒泡阶段触发,默认就是false
// 若是用 L0 事件监听,则只有冒泡阶段,没有捕获

  <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");
        },
        true
      ); // 捕获
      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>

5.事件流总结

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

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

(3)捕获阶段 父节点 流动到 子节点

(4)我们可以修改触发事件 让它选择使用 捕获阶段还是冒泡阶段(默认)

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

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

​ addEventListener("click",function(){}, true )

(5)总结

①捕获和冒泡特点 :捕获阶段是 从父到子 冒泡阶段是从子到父

②默认情况 冒泡 如果想要修改 可以 addEventListener 第三个参数 传入 true即可

③以后的代码开发过程中,还是继续使用默认的 冒泡阶段

6.阻止冒泡事件

(1)关键阻止冒泡代码

// 阻止事件冒泡
event.stopPropagation();

(2)原理理解:当点击子元素时,捕获事件从父元素开始到子元素,因此首先展现的属性为父元素属性(如:给子元素添加阻止冒泡的代码时,将阻止父元素冒泡)

    <script>
      const p = document.querySelector("p");

      const a = document.querySelector(".a");
      a.addEventListener("click", function () {
        p.style.backgroundColor = "red";
        p.innerText = +p.innerText + 1;
        console.log("a");
      });
      const b = document.querySelector(".b");
      b.addEventListener("click", function (event) {
        console.log("b");
        p.innerText = +p.innerText + 10;
        p.style.backgroundColor = "blue";
        // 阻止事件冒泡
        event.stopPropagation();
      });
      const c = document.querySelector(".c");
      c.addEventListener("click", function (event) {
        console.log("c");
        p.innerText = +p.innerText + 100;
        p.style.backgroundColor = "green";

        // 阻止事件冒泡
        event.stopPropagation();
      });
      const d = document.querySelector(".d");
      d.addEventListener("click", function (event) {
        console.log("d");
        p.innerText = +p.innerText + 100;
        p.style.backgroundColor = "pink";

        // 阻止事件冒泡
        event.stopPropagation();
      });

      /* 
      引出新的知识 阻止冒泡! 下一节课 优雅的方式来解决刚才的问题! 
      在事件对象中 event 找到一个方法 停止冒泡  event.stopPropagation();
      
       */
    </script>

7.阻止标签默认行为

(1)a标签的点击跳转

(2)form表单中button点击刷新行为

①阻止默认行为 - form表单 有一个 submit 事件 理解提交表单的触发-点击按钮的时候触发

② 给button按钮绑定点击事件 也去阻止试试

③给button按钮 添加一个 type="button" 属性

④换成 input标签 type="button"

⑤把button 移出form表单的区域

⑥使用新技术 阻止标签默认行为

(3)关键代码展示

// 阻止默认行为代码
// event.preventDefault();


// 补充添加刷新功能 form标签,原理:去除默认属性,添加新功能-刷新
<form>
  <!-- <button type="button">点击我 就会自动刷新</button> -->
  <!-- <input type="button" value="点击我"> -->
  <button>刷新</button>
</form>
<body>
    <a href="http://www.baidu.com">百度</a>
    <form>
      <!-- <button type="button">点击我 就会自动刷新</button> -->
      <!-- <input type="button" value="点击我"> -->
      <button>刷新</button>
    </form>
    <script>
      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>
  </body>

8.阻止默认行为案例---鼠标右键

(1)思路

①写死标签样式(隐藏ul列表)

② js部分

​ 注册事件(跟随鼠标移动 获取 左边、 重新显现ul列表)

​ 绑定事件类型

​ 功能内容:点击右键 出现选项列表(取消默认功能、注册点击事件---重新隐藏列表)

(2)代码

js关键代码

// 事件类型 鼠标右键contextmenu  触发
document.body.addEventListener("contextmenu",function(){})

// 阻止鼠标右键原有的默认功能/行为
event.preventDefault();

html部分添加的骨架代码

    <ul class="menu">
      <li>打开</li>
      <li>查看</li>
      <li>属性</li>
      <li>返回桌面</li>
    </ul>

css部分代码

    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      body {
        height: 100vh;
      }
      .menu {
        list-style: none;
        padding: 10px;
        border-radius: 5px;
        border: 1px solid #ccc;
        width: 150px;
        /* 绝对定位   通过js获取鼠标定位 赋值left 和 top 
        使标签能够与跟随鼠标移动  
          */
        position: fixed;
        /* 隐藏标签 点击鼠标右键后 显现实现对应功能*/
        display: none;
      }
      li {
        height: 40px;
        display: flex;
        align-items: center;
        padding-left: 10px;
        border-bottom: 1px solid #ccc;
      }
      li:hover {
        background-color: skyblue;
        color: #fff;
        cursor: pointer;
      }
      li:last-child {
        border-bottom: none;
      }
    </style>

js部分代码

    <script>
        //注册事件
      const menu = document.querySelector(".menu");

      //   contextmenu 鼠标右键  绑定事件类型
      document.body.addEventListener("contextmenu", function (event) {
        event.preventDefault();
        // 鼠标位置 clientX/clientY
        const left = event.clientX;
        const top = event.clientY;

        menu.style.display = "block";
        menu.style.left = left + "px";
        menu.style.top = top + "px";
          
          // 绑定点击 body标签时,ul列表隐藏
        document.body.addEventListener("click", function () {
          menu.style.display = "none";
        });
      });
    </script>

二、事件委托

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

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

    <script>
      const ul = document.querySelector("ul");
      ul.addEventListener("click", function (event) {
        if (event.target.nodeName === "LI") {
          // event.target.nodeName 获取标签名

          // event.target.style.backgroundColor="red";
          // console.log(event.target);

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

3.学生信息列表案例

(1)

①定义数组 负责存放表格要显示的数据

②根据数组渲染页面

(2)按钮绑定点击事件

①创建一个新的对象 把表单数据都合并到对象中

②给数组插入新的元素

③数组发生改变 重新调用渲染页面的函数

④表单数据清空

(3)tbody绑定点击事件,同时判断被点击的是不是 del 删除标签

①判断当前点击的是不是a标签

②获取到a标签 上存放的 index

③执行数组删除元素

④调用根据数组渲染页面的函数

<!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>
      // 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标签
        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滚动事件

1.将滚轮添加给对应元素

window.addEventListener("scroll",function (){})
<script>
   // window.addEventListener("scroll",function () {
   //   console.log("我滚啦 你呢");
   // })
   const div = document.querySelector("div");
   div.addEventListener("scroll", function () {
     console.log("div又开始滚啦");
   });
   const p = document.querySelector("p");
   p.addEventListener("scroll", function () {
     console.log("p又开始滚啦");
   });
</script>

2.获取当前滚轮滚动的距离

    <script>
      // 页面级别的滚动
      let h1_14 = document.querySelector(".h1_14");
      window.addEventListener("scroll", function () {
        // 这个代码可以获取到当前页面的滚动距离

        console.log(document.documentElement.scrollTop);
      });
    </script>

3.固定导航条案例----效果滚动到一定位置,导航条固定不动

(1)思路:

结构:

<header></header>
<nav></nav>
<div>
  <h1>1</h1>
  <h1>2</h1>
  <h1>3</h1>
  ...
  <h1>100</h1>
</div>

①需要在页面滚动距离 大于或者等于 250 的高时候

②设置nav标签做一个 固定定位

③否则就取消固定定位

④小bug 因为 nav标签做固定定位,不再拥有高度,自然把下面的标签给挡住

⑤给nav上面的标签 header标签 添加下外边距,大小 等于 nav的高

(2)关键代码

//  获取页面滚动的高度
const scrollTop = document.documentElement.scrollTop;

// 判断滚动scrollTop到达多少值时设置固定
 if (scrollTop >= 250) {
          // 添加固定定位
          nav.classList.add("fixed");
          // 给头部标签一个下外边距,决绝脱标问题
          header.style.marginBottom = 150 + "px";
        } else {
          nav.classList.remove("fixed");
          header.style.marginBottom = 0;
        }

(3)CSS实现方式

 nav {
        background-color: orange;
        height: 150px;
        /* 粘性定位 兼容性问题  慎用!  */
        position: sticky;
        left: 0;
        top: 0;
        width: 100%;

四、火箭快速返回案例

1.思路

(1)设置页面的高度 200vh 设置渐变色

(2)先完成静态结构

①定位 右下角 火箭图片

②鼠标移上去 火箭图片切换- 会动的火箭图片

③页面滚动到一定的距离 1500: 让小火箭显示出来, 否则 小火箭就隐藏

(3)代码

①结构代码

 <a href="javascript:;"></a>

②CSS代码

    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      body {
        height: 200vh;
        background-image: linear-gradient(black, red, blue, green);
        // 背景颜色渐变
        / *background-image: linear-gradient(red, blue); */
      }
      a {
        width: 150px;
        height: 195px;
        position: fixed;
        bottom: 100px;
        right: 50px;
        background-image: url(./images/gotop.png);
        display: none;
      }
      a:hover {
        background-image: url(./images/gotop.gif);
      }
    </style>

(3)js代码

    <script>
      /* 
      步骤:
      1 设置页面的高度 200vh  设置渐变色
      2 先完成静态结构
        1 定位 右下角 火箭图片
        2 鼠标移上去 火箭图片切换- 会动的火箭图片
      3 页面滚动到一定的距离  1500
        让小火箭显示出来
        否则 小火箭就隐藏
       */

      const a = document.querySelector("a");
      const body = document.querySelector("body");

      window.addEventListener("scroll", function () {
        //  获取页面滚动的距离
        const scrollTop = document.documentElement.scrollTop;
        if (scrollTop > 700) {
          // 显示火箭
          a.style.display = "block";
        } else {
          // 隐藏
          a.style.display = "none";
        }
      });
       
      a.addEventListener("click", function () {
        // 定时器 结合 滚轮距离 逐步减小 达到缓慢返回顶部的效果
        let timeID = setInterval(function () {
          document.documentElement.scrollTop -= 100;
          console.log("定时器");
          // 清除定时器
          if (document.documentElement.scrollTop <= 0) {
            clearInterval(timeID);
          }
        }, 100);
      });
    </script>