JavaScript 高级事件学习案例

Posted GoldenaArcher

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript 高级事件学习案例相关的知识,希望对你有一定的参考价值。

javascript 高级事件学习案例

JavaScript 基础语法-dom-bom-js es6 新语法-jQuery-数据可视化 echarts 黑马程序员 pink 老师前端入门视频教程(500 多集课程) p247-262 的内容,包含了以下案例:

  1. 两种注册事件的方法
  2. 两种解绑事件的方法
  3. DOM 事件流
    • 捕获事件
    • 冒泡事件
    • 阻止事件冒泡
  4. 事件委托
  5. 鼠标事件
  6. 键盘事件

案例 1 注册事件

以两个方法为主:element.oneventname = fn(){}, eventTarget.addEventListener(type, listenerp, useCapture]);, 还有一个 element.attachEvent() 作为兼容性的辅助方法,了解使用即可

register-event

源码:

<!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>
    <button>传统注册时间</button><button>方法监听注册时间</button>

    <script>
      const btns = document.querySelectorAll("button");
      btns[0].onclick = function () {
        console.log("hi");
      };
      btns[0].onclick = function () {
        console.log("how are u");
      };
      btns[1].addEventListener("click", function () {
        console.log("hello it't me");
      });
      btns[1].addEventListener("click", function () {
        console.log("hello from the other side");
      });
    </script>
  </body>
</html>

案例 2 解绑事件

onevent 的解绑事件比较简单,在操作完成后将其设置为 null 即可。addEventListener 稍微麻烦一些,需要将方法提抽离出来,在方法体内用 removeEventListener 进行解绑。

效果图:

unregister

注意多次点击元素,控制台上只有一行输出,证明事件被激发了一次。

代码:

<!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>
      div {
        margin: 20px auto;
        width: 50px;
        height: 50px;
        background-color: #eee;
      }
    </style>
  </head>
  <body>
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <script>
      const divs = document.querySelectorAll("div");
      divs[0].onclick = function () {
        console.log("divs[0] registered once");
        divs[0].onclick = null;
      };

      function fn() {
        console.log("divs[1] registered once");
        divs[1].removeEventListener("click", fn);
      }

      // 调用不需要加小括号
      divs[1].addEventListener("click", fn);
    </script>
  </body>
</html>

案例 3 DOM 事件流

捕获阶段

从父元素向子元素流动的过程:

capture

代码:

<!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>
      .father {
        box-sizing: border-box;
        margin: 50px auto;
        padding: 50px;
        width: 200px;
        height: 200px;
        background-color: #aaa;
      }
      .child {
        width: 100px;
        height: 100px;
        background-color: #eee;
      }
    </style>
  </head>
  <body>
    <div class="father">
      <div class="child"></div>
    </div>
    <script>
      const child = document.querySelector(".child");
      const father = document.querySelector(".father");

      // 捕获阶段
      child.addEventListener(
        "click",
        function () {
          console.log("child");
        },
        true
      );
      // 捕获阶段2
      father.addEventListener(
        "click",
        function () {
          console.log("father");
        },
        true
      );
    </script>
  </body>
</html>

冒泡阶段

从子元素向父元素流动的过程:

bubble

代码:

// 其余部分与上文一致,仅修改 JS 部分

// 冒泡阶段
child.addEventListener(
  "click",
  function (e) {
    console.log("child");
  },
  false
);
// 冒泡阶段2
father.addEventListener(
  "click",
  function () {
    console.log("father");
  },
  false
);
document.addEventListener(
  "click",
  function () {
    console.log("document");
  },
  false
);

阻止事件冒泡

使用 event.strpPropagation 去阻止冒泡事件:

propagation

比起上面的冒泡时间只多了一行代码:

// 其他部分一样
child.addEventListener(
  "click",
  function (e) {
    console.log("child");
    // 阻止冒泡事件
    e.stopPropagation();
  },
  false
);
// 其他部分一样

案例 4 事件委托

事件委托通俗意义上来说,就是利用事件冒泡,将事件绑定在父节点上,而非绑定每一个子元素,这样可以减少 DOM 的操作,对性能进行提升。

以一个推广为例,正常的推广会有一个图片,一段介绍,正常情况下来说,只要点击图片或是文字介绍都可以超链接转链到商品详情上去。这样的话,就可以直接在父元素上绑定 onclick 事件,而不用循环操作所有的子元素。

注意,事件委托中的 thisevent 并不一定是一样的—— this 指的是绑定的元素,在下列情况下是 card,而 event 是触发点击事件的元素,包含父元素自己和所有的子元素。

效果图:

bubble2

源码:

<!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;
      }
      .card {
        height: 200px;
        width: 150px;
        margin: 80px;
        border: 1px solid #000;
        text-align: center;
      }
      .card:hover {
        cursor: pointer;
      }
      .img {
        width: 100%;
        height: 150px;
        background-color: gray;
        background-image: linear-gradient(
          transparent 50%,
          rgba(255, 255, 255, 0.5) 50%
        );
        background-size: 50px 50px;
      }
    </style>
  </head>
  <body>
    <div class="card">
      <div class="img"></div>
      <h3>假设标题</h3>
      <p class="intro">假设介绍</p>
      <script>
        // this 和 event 是不一样的
        const card = document.querySelector(".card");
        card.addEventListener("click", function (e) {
          console.log(e.srcElement);
          console.log(this);
        });
      </script>
    </div>
  </body>
</html>

案例 5 鼠标事件

案例中使用

  1. 禁止选中内容(感觉好像某图书库,登录 VIP 才能用功能的那个)

  2. 禁止右键获取菜单

  3. 鼠标事件获取了当前视窗的位置,使图标可以悬浮跟随光标。这个功能用的还挺频繁的,例如说 放大镜 功能,可以在地图上用,很多商品图片上也会用到。

    还有就是在地图上插入图标,例如说打卡啊,或者是设置途径地点之类的。

效果图:

mouse-event

代码实现:

<!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>
      svg {
        position: absolute;
      }
    </style>
  </head>
  <body>
    <svg
      t="1620258512730"
      class="icon"
      viewBox="0 0 1024 1024"
      version="1.1"
      xmlns="http://www.w3.org/2000/svg"
      p-id="2475"
      width="50"
      height="50"
    >
      <path
        d="M224.128 155.498667C380.16 2.688 631.786667-0.490667 791.722667 147.712l8.149333 7.786667a394.176 394.176 0 0 1 0 565.589333L512 1002.944 224.128 721.066667a394.176 394.176 0 0 1 0-565.589334zM512 275.2a168.533333 168.533333 0 1 0 0 337.066667 168.533333 168.533333 0 0 0 0-337.066667z m0 64a104.533333 104.533333 0 1 1 0 209.066667 104.533333 104.533333 0 0 1 0-209.066667z"
        fill="#717378"
        p-id="2476"
      ></path>
    </svg>
    onclick,点击事件 onmouseover,鼠标经过触发 onmouseout,鼠标离开触发
    onfocus,获得鼠标焦点触发 onblur,失去鼠标焦点触发 onmousemove,鼠标移动触发
    onmouseup,鼠标弹起触发 onmousedown,鼠标按下触发
    <script>
      // 1. 禁止鼠标右键菜单
      // 使用 contextmenu
      document.addEventListener("contextmenu", function (e) {
        e.preventDefault();
      });
      // 2. 禁止鼠标选中
      // 使用 selectstart

      document.addEventListener("selectstart", function (e) {
        e.preventDefault();
      });
      // 3. 鼠标光标跟随
      document.addEventListener("mousemove", function (e) {
        const svg = document.querySelector("svg");
        const { pageX, pageY } = e;
        [svg.style.left, svg.style.top] = [
          `${pageX - 25}px`,
          `${pageY - 25}px`,
        ];
      });
    </script>
  </body>
</html>

案例 6 键盘事件

模拟的一个快递单号查询功能,输入单号的时候上面会出现一个对话框,上面是放大的快递单号。当单号是空的时候,或者输入框失去焦点是,对话框会隐藏:

kb-event

代码实现:

<!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>
      .enlarged-package-id,
      .enlarged-package-id::after,
      input {
        box-sizing: border-box;
      }
      .enlarged-package-id {
        display: none;
        position: absolute;
        top: 70px;
        left: 108px;
        width: 175px;
        border: 1px solid #ccc;
        margin-bottom: 15px;
        font-size: 20px;
      }
      /* credit: */
      /* https://stackoverflow.com/questions/47318399/how-to-make-a-border-triangle-using-css */
      .enlarged-package-id::after {
        content: "";
        width: 10px;
        height: 10px;
        position: absolute;
        background-color: #fff;
        bottom: -5px; /* half of the elements width/height */
        left: 50%;
        transform: translateX(-50%) rotate(45deg);
        border-bottom: 1px solid #ccc;
        border-right: 1px solid #ccc;
      }
      input {
        margin: 100px;
        border: 1px solid #ccc;
        outline: none;
      }
    </style>
  </head>
  <body>
    <div class="enlarged-package-id"JavaScript高级笔记

JavaScript笔试题(js高级代码片段)

JavaScript 高级事件学习

js-JavaScript高级程序设计学习笔记9

JavaScript高级程序设计(第三版)学习笔记1314章

web前端之JavaScript高级程序设计六:事件