Javascript 自定义对象上的addEventListener

Javascript 自定义对象上的addEventListener,javascript,object,cordova,addeventlistener,Javascript,Object,Cordova,Addeventlistener,我已经创建了一个具有多个方法的对象。其中一些方法是异步的,因此我希望在方法完成时使用事件来执行操作。为此,我尝试将addEventListener添加到对象中 这将返回一个错误:未能添加EventListens:TypeError:“addEventListener”在未实现接口EventTarget的对象上调用。“ 现在,这段代码将在phonegap应用程序中使用,当我这样做时,它将在android/ios上工作。然而,在测试期间,如果我能让它在至少一个浏览器中工作,那就太好了 PS>我知道

我已经创建了一个具有多个方法的对象。其中一些方法是异步的,因此我希望在方法完成时使用事件来执行操作。为此,我尝试将addEventListener添加到对象中

这将返回一个错误:
未能添加EventListens:TypeError:“addEventListener”在未实现接口EventTarget的对象上调用。“

现在,这段代码将在phonegap应用程序中使用,当我这样做时,它将在android/ios上工作。然而,在测试期间,如果我能让它在至少一个浏览器中工作,那就太好了


PS>我知道我可以启用冒泡,然后监听文档根,但我希望有一点OOP,每个对象都可以独立工作。

我认为可以使用object$Deferred和promises。 它会让你做这样的事情:

堆叠:将应用程序中任意位置的多个处理程序绑定到同一承诺事件

  var request = $.ajax(url);
  request.done(function () {
  console.log('Request completed');
});
//应用程序中的其他地方

   request.done(function (retrievedData) {
     $('#contentPlaceholder').html(retrievedData);
   });
并行任务:要求多个承诺返回一个承诺,该承诺提醒双方完成

$.when(taskOne, taskTwo).done(function () {
  console.log('taskOne and taskTwo are finished');
});
顺序任务:按顺序执行任务

 var step1, step2, url;

 url = 'http://fiddle.jshell.net';

 step1 = $.ajax(url);

 step2 = step1.then(
   function (data) {
       var def = new $.Deferred();

       setTimeout(function () {
           console.log('Request completed');
           def.resolve();
       },2000);

     return def.promise();

 },
   function (err) {
       console.log('Step1 failed: Ajax request');
   }
 );
 step2.done(function () {
     console.log('Sequence completed')
     setTimeout("console.log('end')",1000);
 });
资料来源:
本文介绍如何创建自定义事件:

以下是一个例子:

创建事件-

var event = new CustomEvent(
    "newMessage",
    {
        detail: {
            message: "Hello World!",
            time: new Date(),
        },
        bubbles: true,
        cancelable: true
    }
);
将事件分配给以下对象:

document.getElementById("msgbox").dispatchEvent(event);
订阅活动-

document.addEventListener("newMessage", newMessageHandler, false);

addEventListener
适用于实现某些事件相关接口的DOM元素。如果您想要纯JavaScript对象上的事件系统,您需要一个自定义事件系统。例如Backbone.js中的
Backbone.Events
。基本思想是使用对象作为哈希来跟踪已注册的c全能球员

就我个人而言,我使用这个:


这是一个相当简单而优雅的解决方案-使用简短的方法名,如
on()
off()
emit()
。您可以使用
new Emitter()
创建新实例,也可以使用
Emitter(obj)
将事件功能混合到现有对象中。请注意,此库是为与CommonJS模块系统一起使用而编写的,但您可以通过删除
module.exports=…
行在其他任何地方使用它。

存在两个问题

首先,
iSubmit.addEventListener()
方法实际上是
EventTarget
DOM接口上的一个方法:

这些被嵌入仅用于DOM元素。通过将其作为方法添加到
iSubmit
对象中,您正在对不是
EventTarget
的对象调用它。这就是为什么Chrome抛出
未捕获类型错误:非法调用
JavaScript错误

第一个问题很关键,但是如果您可以使用
EventTarget#addEventListener()
,您的代码将无法工作,因为事件将被添加到
iSubmit
,但从
document
发送。通常,在附加事件侦听器和发送事件时需要使用相同对象的方法(除非您使用冒泡事件,注意:冒泡并不限于JavaScript或DOM相关事件,)

对您自己的对象使用自定义事件是非常正常的。因此,有一些库可用于此操作。以下是几个库:

我曾经使用过
jssignals
,并且非常喜欢它。我从未使用过
Wolfy87/EventEmitter
,但是它看起来很不错

如果您使用了
js信号,那么您的示例可能类似于以下内容


如果要侦听javascript对象,有三种方法:

  • 使用在javascript中有很多功能的
  • 或通过使用本机实现,或
  • 使用.Works Chrome 25+(2014年1月)。但在2016年成为
关于sup/pub模式:

const CustomObject = require('./CustomObject');

// 1. Create a new instance
const myObject = new CustomObject();

// 2. Subscribe to events with ID "myEventName"
myObject.on('myEventName', function(event) {
  console.log('Received event', event);
});

// 3. Trigger the event emitter
myObject.doSomething();
您需要发布事件

关于本机实现:

const CustomObject = require('./CustomObject');

// 1. Create a new instance
const myObject = new CustomObject();

// 2. Subscribe to events with ID "myEventName"
myObject.on('myEventName', function(event) {
  console.log('Received event', event);
});

// 3. Trigger the event emitter
myObject.doSomething();
  • 对象获取/设置运算符
    足以侦听添加、删除、更改、, 获取事件。运算符有好的。问题仅限于IE8-。 但是如果您想在IE8中使用get/set,请使用
    Object.defineProperty
    But 在DOM对象上或使用Object.defineProperty
  • Object.prototype.watch
    具有良好的ES5性能
  • 代理API
    需要ES Harmony支持
对象。观察示例

var o = {};
Object.observe(o, function (changes) {
  changes.forEach(function (change) {
    // change.object contains changed object version
    console.log('property:', change.name, 'type:', change.type);
  });
});
o.x = 1     // property: x type: add
o.x = 2     // property: x type: update
delete o.x  // property: x type: delete

如果您不需要真正的事件功能(例如冒泡、停止冒泡),然后您可以实现自己的事件。addEventListener只是DOM的一个API,因此您在DOM之外的对象中并不真正需要它。如果您想围绕对象创建事件模式,下面是一个很好的方法,它不需要任何额外的浏览器API,并且应该非常向后兼容

假设您有一个对象,希望在调用dispatch方法时触发一组事件:

var OurDispatcher, dispatcher;

OurDispatcher = (function() {
  function OurDispatcher() {
    this.dispatchHandlers = [];
  }

  OurDispatcher.prototype.on = function(eventName, handler) {
    switch (eventName) {
      case "dispatch":
        return this.dispatchHandlers.push(handler);
      case "somethingElse":
        return alert('write something for this event :)');
    }
  };

  OurDispatcher.prototype.dispatch = function() {
    var handler, i, len, ref;
    ref = this.dispatchHandlers;
    for (i = 0, len = ref.length; i < len; i++) {
      handler = ref[i];
      setTimeout(handler, 0);
    }
  };

  return OurDispatcher;

})();

dispatcher = new OurDispatcher();

dispatcher.on("dispatch", function() {
  return document.body.innerHTML += "DISPATCHED</br>";
});

dispatcher.on("dispatch", function() {
  return document.body.innerHTML += "DISPATCHED AGAIN</br>";
});

dispatcher.dispatch();
var调度程序,调度程序;
OurDispatcher=(函数(){
函数OurDispatcher(){
this.dispatchHandlers=[];
}
OurDispatcher.prototype.on=函数(eventName,handler){
开关(eventName){
“派遣”一案:
返回此.dispatchHandlers.push(处理程序);
案例“somethingElse”:
返回警报(“为此事件写入内容:)”;
}
};
OurDispatcher.prototype.dispatch=函数(){
变量处理程序,i,len,ref;
ref=这是dispatchHandlers;
对于(i=0,len=ref.length;i”;
});
dispatcher.on(“dispatch”,function()){
return document.body.innerHTML+=“再次发送”
”; }); dispatcher.dispatch();
在大多数情况下,它真的不必比那复杂。这样你就有了一些d
const EventEmitter = require('events');

class CustomObject extends EventEmitter {
  constructor() {
    super();
  }

  doSomething() {
    const event = {message: 'Hello World!'};
    this.emit('myEventName', event);
  }
}

module.exports = CustomObject;
const CustomObject = require('./CustomObject');

// 1. Create a new instance
const myObject = new CustomObject();

// 2. Subscribe to events with ID "myEventName"
myObject.on('myEventName', function(event) {
  console.log('Received event', event);
});

// 3. Trigger the event emitter
myObject.doSomething();
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Title</title>
    <script src="bundle.js"></script>
  </head>
  <body>
    <script>
      // 1. Create a new instance
      const myObject = new window.CustomObject();

      // 2. Subscribe to events with ID "myEventName"
      myObject.on('myEventName', function(event) {
        console.log('Received event', event);
      });

      // 3. Trigger the event emitter
      myObject.doSomething();
    </script>
  </body>
</html>
function myObject(){
    //create "dummy" element
    var dummy = document.createElement('dummy');
    //method for listening for events
    this.on = function(event, func){dummy.addEventListener(event, func);};
    //you need a way to fire events
    this.fireEvent = function(event, obj){
      dummy.dispatchEvent(new CustomEvent(event, {detail: obj}));
    }
}
//now you can use the methods in the object constructor
var obj = new myObject();
obj.on("custom", function(e){console.log(e.detail.result)});
obj.fireEvent("custom", {result: "hello world!!!"});
CustomEventTarget.prototype = {

    'constructor': CustomEventTarget,

    on:   function( ev, el ) { this.eventTarget.addEventListener( ev, el ) },
    off:  function( ev, el ) { this.eventTarget.removeEventListener( ev, el ) },
    emit: function( ev ) { this.eventTarget.dispatchEvent( ev ) }

}

function CustomEventTarget() { this.eventTarget = new EventTarget }
class Events {
  constructor () {
    this._callbacks = {}
  }

  on (key, callback) {
    // create an empty array for the event key
    if (this._callbacks[key] === undefined) { this._callbacks[key] = [] }
    // save the callback in the array for the event key
    this._callbacks[key].push(callback)
  }

  emit (key, ...params) {
    // if the key exists
    if (this._callbacks[key] !== undefined) {
      // iterate through the callbacks for the event key
      for (let i=0; i<this._callbacks[key].length; i++) {
        // trigger the callbacks with all provided params
        this._callbacks[key][i](...params)
      }
    }
  }
}


// EXAMPLE USAGE

class Thing extends Events {
  constructor () {
    super()
    setInterval(() => {
      this.emit('hello', 'world')
    }, 1000)
  }
}

const thing = new Thing()

thing.on('hello', (data) => {
  console.log(`hello ${data}`)
})
/*
 * object.watch polyfill
 *
 * 2012-04-03
 *
 * By Eli Grey, http://eligrey.com
 * Public Domain.
 * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
 * https://gist.github.com/eligrey/384583
 */

// object.watch
if (!Object.prototype.watch) {
    Object.defineProperty(Object.prototype, "watch", {
          enumerable: false
        , configurable: true
        , writable: false
        , value: function (prop, handler) {
            var
              oldval = this[prop]
            , newval = oldval
            , getter = function () {
                return newval;
            }
            , setter = function (val) {
                oldval = newval;
                return newval = handler.call(this, prop, oldval, val);
            }
            ;

            if (delete this[prop]) { // can't watch constants
                Object.defineProperty(this, prop, {
                      get: getter
                    , set: setter
                    , enumerable: true
                    , configurable: true
                });
            }
        }
    });
}

// object.unwatch
if (!Object.prototype.unwatch) {
    Object.defineProperty(Object.prototype, "unwatch", {
          enumerable: false
        , configurable: true
        , writable: false
        , value: function (prop) {
            var val = this[prop];
            delete this[prop]; // remove accessors
            this[prop] = val;
        }
    });
}
var object = {
    value: null,
    changeValue: function(newValue) {
        this.value = newValue;
    },
    onChange: function(callback) {
        this.watch('value', function(obj, oldVal, newVal) {
            // obj will return the object that received a change
            // oldVal is the old value from the object
            // newVal is the new value from the object

            callback();
            console.log("Object "+obj+"'s value got updated from '"+oldValue+"' to '"+newValue+"'");
            // object.changeValue("hello world");
            // returns "Object object.value's value got updated from 'null' to 'hello world'";

            // and if you want the function to stop checking for
            // changes you can always unwatch it with:
            this.unwatch('value');

            // you can retrieve information such as old value, new value
            // and the object with the .watch() method, learn more here:
            // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/watch
        })
    }
};
var object = { user: null };

// add a watch to 'user' value from object
object.watch('user', function() {
    // object user value changed
});
class EventEmitter {
    on(name, callback) {
        var callbacks = this[name];
        if (!callbacks) this[name] = [callback];
        else callbacks.push(callback);
    }

    dispatch(name, event) {
        var callbacks = this[name];
        if (callbacks) callbacks.forEach(callback => callback(event));
    }
}
var emitter = new EventEmitter();

emitter.on('test', event => {
    console.log(event);
});

emitter.dispatch('test', 'hello world');
class MyClass
{   
    
    constructor(options ) 
    {     
    
  
        this.el =  document.createElement("MyClass");//dummy element to manage events.    
        this.el.obj= this; //So that it is accessible via event.target.obj
      
    }

    addEventListener()
    {
 
        this.el.addEventListener(arguments[0],arguments[1]);

    }
    
 

     raiseEvent()
         {
//call this function or write code below when the event needs to be raised.

            var event = new Event('dataFound');
            event.data = messageData;
            this.el.dispatchEvent(event);
        }
}


let obj = new MyClass();
obj.addEventListener('dataFound',onDataFound);

function onDataFound()
{ 
console.log('onDataFound Handler called');
}