如何用Javascript实现一个完整的事件系统



我正在创建一个客户端动态博客引擎。现在我需要一个事件系统来处理来自DOM元素和引擎的许多操作。例如引擎正在加载一篇文章,用户正在切换主题…

我不想用库来做这个

到目前为止,我已经完成了使用列表存储事件的回调

但我希望每个回调工作与不同的对象。像DOM事件。

我可以为每个对象添加一个类似id的属性,并在事件中存储(id,回调)。我觉得不太好。当使用动态生成的对象时,处理起来可能会很复杂。

如何实现它简单的DOM事件(使用)?

最近,我想向普通JavaScript对象添加简单的事件侦听器。这就是我想到的解决方案

(这需要ecmascript >= 5)

function Emitter () {
  var eventTarget = document.createDocumentFragment();
  function delegate (method) {
    this[method] = eventTarget[method].bind(eventTarget);
  }
  Emitter.methods.forEach(delegate, this);
}
Emitter.methods = ["addEventListener", "dispatchEvent", "removeEventListener"];

现在是一个使用它的"类"

function Example () {
  Emitter.call(this);
}

让我们现在就试试吧!

var e = new Example();
e.addEventListener("something", function(event) {
  alert("something happened! check the console too!");
  console.log(event);
});
e.dispatchEvent(new Event("something"));

祝你好运!

您可以实现中介模式:

http://addyosmani.com/resources/essentialjsdesignpatterns/book/mediatorpatternjavascript

这本书里有你需要知道的关于它的一切。

class SimpleEvent {
  constructor() {
    this.onEvent = {}
    this.handler = function(funct, name) {
      var owner = this
      var name = name
      this.onEvent[name] = funct
      var remove = function() {
        delete this.owner.onEvent[this.name]
        delete this.owner
        delete this.name
        delete this.remove
      }
      if ((((!(remove == undefined && name == undefined)) && (remove == undefined || name == undefined)))) {
        throw new Error("-_-")
      } else {
        return (remove == undefined || name == undefined) ? (undefined) : ({
          remove: remove,
          name: name
        })
      }
    }
  }
  Fire() {
    for (var i in this.onEvent) {
      this.onEvent[i](arguments)
    }
  }
}

ok,我最近正在研究这个解决这个https://github.com/browserify/events#readme只是为了使它在我的个人环境中保持一致,但我也想粘贴一个基本的我在光滑网格项目中发现的这是非常有用的,只有150行代码,我认为给了一个很好的基本理解事件

/***
 * An event object for passing data to event handlers and letting them control propagation.
 * <p>This is pretty much identical to how W3C and jQuery implement events.</p>
 * @class EventData
 * @constructor
 */
function EventData() {
  var isPropagationStopped = false;
  var isImmediatePropagationStopped = false;
  /***
   * Stops event from propagating up the DOM tree.
   * @method stopPropagation
   */
  this.stopPropagation = function() {
    isPropagationStopped = true;
  };
  /***
   * Returns whether stopPropagation was called on this event object.
   * @method isPropagationStopped
   * @return {Boolean}
   */
  this.isPropagationStopped = function() {
    return isPropagationStopped;
  };
  /***
   * Prevents the rest of the handlers from being executed.
   * @method stopImmediatePropagation
   */
  this.stopImmediatePropagation = function() {
    isImmediatePropagationStopped = true;
  };
  /***
   * Returns whether stopImmediatePropagation was called on this event object.
   * @method isImmediatePropagationStopped
   * @return {Boolean}
   */
  this.isImmediatePropagationStopped = function() {
    return isImmediatePropagationStopped;
  };
}
/***
 * A simple publisher-subscriber implementation.
 * @class Event
 * @constructor
 */
function Event() {
  var handlers = [];
  /***
   * Adds an event handler to be called when the event is fired.
   * <p>Event handler will receive two arguments - an <code>EventData</code> and the <code>data</code>
   * object the event was fired with.<p>
   * @method subscribe
   * @param fn {Function} Event handler.
   */
  this.subscribe = function(fn) {
    handlers.push(fn);
  };
  /***
   * Removes an event handler added with <code>subscribe(fn)</code>.
   * @method unsubscribe
   * @param fn {Function} Event handler to be removed.
   */
  this.unsubscribe = function(fn) {
    for (var i = handlers.length - 1; i >= 0; i--) {
      if (handlers[i] === fn) {
        handlers.splice(i, 1);
      }
    }
  };
  /***
   * Fires an event notifying all subscribers.
   * @method notify
   * @param args {Object} Additional data object to be passed to all handlers.
   * @param e {EventData}
   *      Optional.
   *      An <code>EventData</code> object to be passed to all handlers.
   *      For DOM events, an existing W3C/jQuery event object can be passed in.
   * @param scope {Object}
   *      Optional.
   *      The scope ("this") within which the handler will be executed.
   *      If not specified, the scope will be set to the <code>Event</code> instance.
   */
  this.notify = function(args, e, scope) {
    e = e || new EventData();
    scope = scope || this;
    var returnValue;
    for (var i = 0; i < handlers.length && !(e.isPropagationStopped() || e.isImmediatePropagationStopped()); i++) {
      returnValue = handlers[i].call(scope, e, args);
    }
    return returnValue;
  };
}
function EventHandler() {
  var handlers = [];
  this.subscribe = function(event, handler) {
    handlers.push({
      event: event,
      handler: handler
    });
    event.subscribe(handler);
    return this; // allow chaining
  };
  this.unsubscribe = function(event, handler) {
    var i = handlers.length;
    while (i--) {
      if (handlers[i].event === event &&
        handlers[i].handler === handler) {
        handlers.splice(i, 1);
        event.unsubscribe(handler);
        return;
      }
    }
    return this; // allow chaining
  };
  this.unsubscribeAll = function() {
    var i = handlers.length;
    while (i--) {
      handlers[i].event.unsubscribe(handlers[i].handler);
    }
    handlers = [];
    return this; // allow chaining
  };
}
console.log("Start Demo")
car1 = {}
car1.onhonk = new Event();
car1.honk = ()=>{
  console.log('car1 Honked');
  car1.onhonk.notify({noise:'meep meep'}) 
};

car2 = {}
car2.honkListener = (e, args) => {
  console.log("car2 heard: ", args.noise);
}
car1.honk();//not heard yet 
car1.onhonk.subscribe(car2.honkListener);
car1.honk();

相关内容

  • 没有找到相关文章

最新更新