JavaScript系列——事件

2019-05-09  本文已影响0人  fejavu

事件的定义

在W3的定义
中,事件具有三个状态,分别对应三个状态码,1,2,3.有多个可读的属性,常用的比如目标(target),当前目标(currentTarget),还有阻止继续事件传播(captrue/bubble)方法,stopPropagation。


  // PhaseType
  const unsigned short      CAPTURING_PHASE                = 1;
  const unsigned short      AT_TARGET                      = 2;
  const unsigned short      BUBBLING_PHASE                 = 3;

  readonly attribute DOMString        type;
  readonly attribute EventTarget      target;
  readonly attribute EventTarget      currentTarget;
  readonly attribute unsigned short   eventPhase;
  readonly attribute boolean          bubbles;
  readonly attribute boolean          cancelable;
  readonly attribute DOMTimeStamp     timeStamp;
  void               stopPropagation();
  void               preventDefault();
  void               initEvent(in DOMString eventTypeArg, 
                               in boolean canBubbleArg, 
                               in boolean cancelableArg);
};

事件的传播

在 JavaScript 中,时间传播分为三个阶段:

Capture operates from the top of the tree, generally the Document, downward, making it the symmetrical opposite of bubbling which is described below. www.w3.org

在 addEventListener 函数中,可以设置 useCaptrue 为 true,在window 自下而上传导的过程中就捕捉:

ele.addEventListener("event", handle, true);

目标触发:事件到达目标之后执行,例如 onclick 等函数。
冒泡阶段:事件从目标节点回传到 window 对象。

我们用下面的代码做一下实验:

<html>
<head>
  <meta charset="utf-8">
  <title>Exep</title>
</head>
<body>
<div>
  <p>click me</p>
</div>
  <script>
    var container = document.querySelector('div');
    var para = document.querySelector('p');

    var phase = {
      1: "capture",
      2: "target",
      3: "bubble"
    };

    container.addEventListener('click',handle,true);
    para.addEventListener('click',handle,true);
    container.addEventListener('click',handle,false);
    para.addEventListener('click',handle,false);

    function handle(event) {
      var tag = event.currentTarget.tagName;
      var phaseName = phase[event.eventPhase];
      console.log("tag: " + tag + ".phase: " + phaseName);
    }
  </script>
</body>
</html>
/* log
"tag: DIV.phase: capture"
"tag: P.phase: target"
"tag: P.phase: target"
"tag: DIV.phase: bubble" 
*/

EventTarget

eventTarget 有三个方法 分别是 addEventListener 和removeEventListener,dispatchEvent();

target.addEventListener(type, listener[, useCaptrue]);该方法用于在某节点或对象中监听特定事件(listener)。useCpatrue 可以设置为 true,是在捕获阶段监听,false为冒泡阶段监听,默认为false。

如果使用 ele.on-handle 监听事件,则只会在冒泡阶段触发。on-函数是元素的一个属性值,可以在setAttribute 中赋值。

EventTarget.addEventListener 和 on-handle 的区别:

  1. addEventListener 可以同一个设置多个监听函数。
  2. 能够事件哪个阶段(捕获/冒泡)触发监听函数。
  3. 所有的文档对象都可以使用 addEventListener 接口。

on-handle 的缺点:

  1. 违反了 HTML 和 JavaScript 分离的代码规范,不易于模块化和拓展性。
  2. 一个事件只能定义一个监听函数,后定义者后来居上。

事件的代理

由于事件的传播机制,可以将子节点的事件绑定到父节点,然后利用event.target 定位到该元素

// html
<div class="flipBox">
  <div class="login"></div>
</div>

// javasript
$('.flipBox').addEventListener('click', function(e){
  e.stopPropagation();
  if(e.target.classList.contains('login')) {
    $('.flipBox').classList.remove('register');
    $('.flipBox').classList.add('login');
}

this 的指向

听函数内部的this指向触发事件的那个元素节点。

// HTML 
// <button id="btn">点击</button>
var btn = document.getElementById('btn');

// 写法一
btn.onclick = function () {
  console.log(this.id);
};

// 写法二
btn.addEventListener(
  'click',
  function (e) {
    console.log(this.id);
  },
  false
);
// 输出 "btn"

参考阅读

  1. 事件的模型,阮一峰
  2. Document Object Model Events,W3
上一篇 下一篇

猜你喜欢

热点阅读