Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DOM进阶之EventTarget #188

Open
FrankKai opened this issue Mar 19, 2020 · 0 comments
Open

DOM进阶之EventTarget #188

FrankKai opened this issue Mar 19, 2020 · 0 comments
Labels

Comments

@FrankKai
Copy link
Owner

FrankKai commented Mar 19, 2020

之所以学EventTarget,是因为Element对象是最终继承自这个interface的。
这个interface在前端事件方面扮演着非常重要的作用,addEventListener,removeEventListener和dispatchEvent都是在这个interface内部实现的。

image

  • EventTarget概览
  • EventTarget Constructor
    • 最简单的例子
    • 如何自定义一个object 类型([object Number], [object FrankKaiClass])
  • EventTarget Methods
  • EventTarget 简单实现

EventTarget概览

  • EventTarget是一个DOM interface,对象会对它做implement。从而可以接收事件并设置listener。
  • Element,Document,Window是最通用的event target,但是其他的object也可以是event target,例如XMLHttpRequest,AudioNode,AudioContext等等
  • 许多event targets(包括elements,documents,windows)都支持通过onevent设置event-handler。

EventTarget Constructor

最简单的例子

var myEventTarget = new EventTarget();

image
由上图可以看出,EventTarget interface上有addEventListener,dispatchEvent和removeEventListener三个方法,而且Symbol(Symbol.toStringTag)是"EventTarget"。

自定义EventTarget实例继承EventTarget interface

class MyEventTarget extends EventTarget {
  constructor(mySecret) {
    super();
    this._secret = mySecret;
  }
  get secret() { return this._secret; }
};

let myEventTarget = new MyEventTarget(5);
let value = myEventTarget.secret;  // == 5
myEventTarget.addEventListener("foo", function(e) {
  this._secret = e.detail;
});

let event = new CustomEvent("foo", { detail: 7 });
myEventTarget.dispatchEvent(event);
let newValue = myEventTarget.secret; // == 7

拓展思考

Symbol.toStringTag是什么?

  • Symbol.toStringTag是一个众所周知的symbol属性,用来创建对象默认字符串描述。Well-known Symbols还包括hasInstance,match,replace等等。
  • 在Object.prototype.toString()内部是可以访问到它的。

一目了然的demo, 可以学会如何自定义一个object 类型([object Number], [object FrankKaiClass])

class FrankKaiClass {
    get [Symbol.toStringTag]() {
        return 'FrankKaiClass';
    }
}
console.log(Object.prototype.toString.call(new FrankKaiClass()));
// [object FrankKaiClass]

EventTarget Methods

  • EventTarget.addEventListener(type, listener[,options]) 注册一个指定event类型的event handler。
  • EventTarget.removeEventListener(type, listener[,options])从EventTarget上移除一个之前通过addEventListener添加的event listener。
  • EventTarget.dispatchEvent() Dispatch一个event到这个EventTarget。

EventTarget 简单实现

var EventTarget = function() {
  this.listeners = {};
};

EventTarget.prototype.listeners = null;
EventTarget.prototype.addEventListener = function(type, callback) {
  if (!(type in this.listeners)) {
    this.listeners[type] = [];
  }
  this.listeners[type].push(callback);
};

EventTarget.prototype.removeEventListener = function(type, callback) {
  if (!(type in this.listeners)) {
    return;
  }
  var stack = this.listeners[type];
  for (var i = 0, l = stack.length; i < l; i++) {
    if (stack[i] === callback){
      stack.splice(i, 1);
      return;
    }
  }
};

EventTarget.prototype.dispatchEvent = function(event) {
  if (!(event.type in this.listeners)) {
    return true;
  }
  var stack = this.listeners[event.type].slice();

  for (var i = 0, l = stack.length; i < l; i++) {
    stack[i].call(this, event);
  }
  return !event.defaultPrevented;
};

参考资料:https://developer.mozilla.org/en-US/docs/Web/API/EventTarget

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant