CLASS中的自定义事件

时间:2013-06-18 09:20:08

标签: javascript jquery

我需要从CLASS启动自定义事件。我知道用DOM对象和jquery做这个,使用triggerHandler,比如$(object).. triggerHandler(“inputChange”,{param:X}); 问题是当我尝试使用类时,如下所示:

    var MyClass = (function(){

        var static_var = 1;

        var MyClass = function () {

            var privateVar;
            var privateFn = function(){ alert('Im private!'); };

            this.someProperty = 5;
            this.someFunction = function () {
                alert('Im public!');
            };
            this.say = function() {
                alert('Num ' + this.someProperty);
                $(this).triggerHandler("eventCustom");
            }
            this.alter = function() {
                this.someProperty ++;
            }
        };

        return MyClass;

    })();

    TheClass = new MyClass();

    $(TheClass).on('eventCustom', function() {
        alert('Event!');
    });

    TheClass.say();

这不会启动警告或错误,但事件侦听器不起作用(或者不调度事件)。我认为jQuery事件系统不能用于DOM对象,对吗?

任何其他方式(我需要事件,而不是针对我的特定情况的回调)才能启动事件?

非常感谢!

2 个答案:

答案 0 :(得分:8)

由于您从传统的OOP角度来看,因此您对javascript如何工作的理解是有限的。看看这个小提琴http://jsfiddle.net/9pCmh/&您将看到您实际上可以将函数作为变量传递给其他函数。 javascript中没有类,只有可以闭包的函数可以模拟传统类:

var MyClass = (function(){

    var static_var = 1;

    var MyClass = function ( callback ) {

        var privateVar;
        var privateFn = function(){ alert('Im private!'); };

        this.someProperty = 5;
        this.someFunction = function () {
            alert('Im public!');
        };
        this.say = function() {
            alert('Num ' + this.someProperty);
            callback();
        }
        this.alter = function() {
            this.someProperty ++;
        }
    };

    return MyClass;

})();

TheClass = new MyClass(function() {
    alert('Event!');
});

TheClass.say();

或者你可以在你的"类"中创建一个函数。配置回调/触发器而不是将其传递给构造函数。

看看这个作为您进一步阅读此概念的开始...... How do JavaScript closures work?

修改

安抚那些寻找eventQueue的评论家这里是一个更新的jsfiddle:)

http://jsfiddle.net/Qxtnd/9/

var events = new function() {
  var _triggers = {};

  this.on = function(event,callback) {
      if(!_triggers[event])
          _triggers[event] = [];
      _triggers[event].push( callback );
    }

  this.triggerHandler = function(event,params) {
      if( _triggers[event] ) {
          for( i in _triggers[event] )
              _triggers[event][i](params);
      }
  }
};

var MyClass = (function(){

      var MyClass = function () {

          this.say = function() {
              alert('Num ' + this.someProperty);
              events.triggerHandler('eventCustom');
          }
      };

      return MyClass;

  })();

  TheClass = new MyClass();

  events.on('eventCustom', function() {
      alert('Event!');
  });
  events.on('eventCustom', function() {
      alert('Another Event!');
  });

  TheClass.say();

答案 1 :(得分:1)

我现在使用100行以下代码编写了一个ES6事件类,而没有使用JQuery。如果您不想使用DOM事件,则可以扩展您的类,该类应处理事件。

要收听事件,可以使用 on,on,OnReady,onceonReady 。每次触发标签时,执行回调函数为On。一次只有一次。如果标签之前已被触发,则“就绪”功能将执行回调。

要触发事件,请使用触发器。要删除事件处理程序,请使用off。

我希望这个例子可以清楚地说明:

class ClassEventsES6 {
                constructor() {
                    this.listeners = new Map();
                    this.onceListeners = new Map();
                    this.triggerdLabels = new Map();
                }

                // help-function for onReady and onceReady
                // the callbackfunction will execute, 
                // if the label has already been triggerd with the last called parameters
                _fCheckPast(label, callback) {
                    if (this.triggerdLabels.has(label)) {
                        callback(this.triggerdLabels.get(label));
                        return true;
                    } else {
                        return false;
                    }
                }

                // execute the callback everytime the label is trigger
                on(label, callback, checkPast = false) {
                    this.listeners.has(label) || this.listeners.set(label, []);
                    this.listeners.get(label).push(callback);
                    if (checkPast)
                        this._fCheckPast(label, callback);
                }

                // execute the callback everytime the label is trigger
                // check if the label had been already called 
                // and if so excute the callback immediately
                onReady(label, callback) {
                    this.on(label, callback, true);
                }

                // execute the callback onetime the label is trigger
                once(label, callback, checkPast = false) {
                    this.onceListeners.has(label) || this.onceListeners.set(label, []);
                    if (!(checkPast && this._fCheckPast(label, callback))) {
                        // label wurde nocht nicht aufgerufen und 
                        // der callback in _fCheckPast nicht ausgeführt
                        this.onceListeners.get(label).push(callback);
                }
                }
                // execute the callback onetime the label is trigger
                // or execute the callback if the label had been called already
                onceReady(label, callback) {
                    this.once(label, callback, true);
                }

                // remove the callback for a label
                off(label, callback = true) {
                    if (callback === true) {
                        // remove listeners for all callbackfunctions
                        this.listeners.delete(label);
                        this.onceListeners.delete(label);
                    } else {
                        // remove listeners only with match callbackfunctions
                        let _off = (inListener) => {
                            let listeners = inListener.get(label);
                            if (listeners) {
                                inListener.set(label, listeners.filter((value) => !(value === callback)));
                            }
                        };
                        _off(this.listeners);
                        _off(this.onceListeners);
                }
                }

                // trigger the event with the label 
                trigger(label, ...args) {
                    let res = false;
                    this.triggerdLabels.set(label, ...args); // save all triggerd labels for onready and onceready
                    let _trigger = (inListener, label, ...args) => {
                        let listeners = inListener.get(label);
                        if (listeners && listeners.length) {
                            listeners.forEach((listener) => {
                                listener(...args);
                            });
                            res = true;
                        }
                    };
                    _trigger(this.onceListeners, label, ...args);
                    _trigger(this.listeners, label, ...args);
                    this.onceListeners.delete(label); // callback for once executed, so delete it.
                    return res;
                }
            }
            
// +++ here starts the example +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
class TestClassEvents extends ClassEventsES6 {
     constructor() {
        super();
        this.once('sayHallo', this.fStartToTalk);
        this.on('sayHallo', this.fSayHallo);
     }

     fStartToTalk() {
         console.log('I start to talk... ');
     }

     fSayHallo(name = 'Nobody') {
        console.log('Hallo ' + name);
     }
}

let testClassEvents = new TestClassEvents();

testClassEvents.trigger('sayHallo', 'Tony');
testClassEvents.trigger('sayHallo', 'Tim');

testClassEvents.onReady('sayHallo', e => console.log('I already said hello to ' + e));
testClassEvents.trigger('sayHallo', 'Angie');
testClassEvents.off('sayHallo');
testClassEvents.trigger('sayHallo', 'Peter');
console.log('I dont say hallo to Peter, because the event is off!')