【问题标题】:Event listener on non-DOM elements非 DOM 元素上的事件监听器
【发布时间】:2014-02-18 18:43:37
【问题描述】:

我正在尝试实现一个小的 MVC 框架,现在我正在实现视图模型绑定器,我的意思是,当模型更改时,触发模型上的刷新/渲染/任何内容。所以,我需要一个对象上的事件监听器:

model.on("customEvent",appendItem);

$("#button").on("click",function(){
    model.add(item);
    model.trigger("customEvent");
});

function appendItem(item) {
   $("#content").append(item.toHTML());
}

那么我怎样才能在对象上创建我的事件监听器呢?

【问题讨论】:

标签: javascript jquery events object


【解决方案1】:

如果您已经在使用 jQuery,则可以使用其内置的事件处理工具。

一个鲜为人知的事实是,您还可以将任何类型的 Javascript 对象放入 jQuery 集合中,而不仅仅是 DOM 元素。然后,您可以在这些对象上使用一组有限的 jQuery 方法(.data().prop().on().off().trigger().triggerHandler())。

//create the model - it can be any kind of object
var model = {};

//pass it to the jQuery function and you have a jQuery collection
//you can put an event handler on the object
$(model).on('customEvent', function () { console.log('hehe'); });

//and trigger it
$(model).trigger('customEvent');

【讨论】:

  • 问题是我的模型是这样构建的 var Model= function() { } 所以不是对象构建 var = {}
  • @user2657856 它是如何构建的并不重要。我很确定它是一个对象;)。
【解决方案2】:

对于那些不使用 jQuery 并且对连接自己的 stuf 感兴趣的人,您可以通过以下方式实现类似的目标:

/**
 * EventfulObject constructor/base.
 * @type EventfulObject_L7.EventfulObjectConstructor|Function
 */
var EventfulObject = function() {
  /**
   * Map from event name to a list of subscribers.
   * @type Object
   */
  var event = {};
  /**
   * List of all instances of the EventfulObject type.
   * @type Array
   */
  var instances = [];
  /**
   * @returns {EventfulObject_L1.EventfulObjectConstructor} An `EventfulObject`.
   */
  var EventfulObjectConstructor = function() {
    instances.push(this);
  };
  EventfulObjectConstructor.prototype = {
    /**
     * Broadcasts an event of the given name.
     * All instances that wish to receive a broadcast must implement the `receiveBroadcast` method, the event that is being broadcast will be passed to the implementation.
     * @param {String} name Event name.
     * @returns {undefined}
     */
    broadcast: function(name) {
      instances.forEach(function(instance) {
        (instance.hasOwnProperty("receiveBroadcast") && typeof instance["receiveBroadcast"] === "function") &&
        instance["receiveBroadcast"](name);
      });
    },
    /**
     * Emits an event of the given name only to instances that are subscribed to it.
     * @param {String} name Event name.
     * @returns {undefined}
     */
    emit: function(name) {
      event.hasOwnProperty(name) && event[name].forEach(function(subscription) {
        subscription.process.call(subscription.context);
      });
    },
    /**
     * Registers the given action as a listener to the named event.
     * This method will first create an event identified by the given name if one does not exist already.
     * @param {String} name Event name.
     * @param {Function} action Listener.
     * @returns {Function} A deregistration function for this listener.
     */
    on: function(name, action) {
      event.hasOwnProperty(name) || (event[name] = []);
      event[name].push({
        context: this,
        process: action
      });

      var subscriptionIndex = event[name].length - 1;

      return function() {
        event[name].splice(subscriptionIndex, 1);
      };
    }
  };

  return EventfulObjectConstructor;
}();

var Model = function(id) {
  EventfulObject.call(this);
  this.id = id;
  this.receiveBroadcast = function(name) {
    console.log("I smell another " + name + "; and I'm model " + this.id);
  };
};
Model.prototype = Object.create(EventfulObject.prototype);
Model.prototype.constructor = Model;

// ---------- TEST AND USAGE (hopefully it's clear enough...)
// ---------- note: I'm not testing event deregistration.

var ob1 = new EventfulObject();
ob1.on("crap", function() {
  console.log("Speaking about craps on a broadcast? - Count me out!");
});

var model1 = new Model(1);

var model2 = new Model(2);
model2.on("bust", function() {
  console.log("I'm model2 and I'm busting!");
});

var ob2 = new EventfulObject();
ob2.on("bust", function() {
  console.log("I'm ob2 - busted!!!");
});
ob2.receiveBroadcast = function() {
  console.log("If it zips, I'll catch it. - That's me ob2.");
};

console.log("start:BROADCAST\n---------------");
model1.broadcast("crap");
console.log("end  :BROADCAST\n---------------\n-\n-\n");
console.log("start:EMIT\n---------------");
ob1.emit("bust");
console.log("end:EMIT\n---------------");
<h1>THE CODE IS IN THE JavaScript SECTION!</h1>
<h3>AND... THE SHOW IS ON YOUR CONSOLE!</h3>

【讨论】:

    猜你喜欢
    • 2022-01-17
    • 2021-03-17
    • 2013-10-06
    • 2014-05-11
    • 2020-06-26
    • 2016-03-19
    • 2010-12-22
    • 2012-11-28
    • 1970-01-01
    相关资源
    最近更新 更多