2012-03-12 14 views
39

Me preguntaba si alguien me puede ayudar a entender exactamente cómo crear diferentes oyentes de eventos personalizados.JavaScript Custom Listener de evento

No tengo un caso específico de un evento pero quiero aprender en general cómo se hace, así que puedo aplicarlo donde sea necesario.

Lo que estaba buscando para hacer, sólo en caso de que algunas personas podrían necesitar saber, fue:

var position = 0; 

for(var i = 0; i < 10; i++) 
{ 
    position++; 
    if((position + 1) % 4 == 0) 
    { 
     // do some functions 
    } 
} 
+0

Ver [esta otra pregunta] (http://stackoverflow.com/questions/2490825/how-to-trigger-event-in-javascript) – bfavaretto

+0

Puede usar una biblioteca como jQuery para crear oyentes y eventos personalizados. Eche un vistazo a http://fuelyourcoding.com/jquery-custom-events-they-will-rock-your-world/ y http://api.jquery.com/trigger/ –

+11

¿Cómo se relaciona el código que publicó? manejo de eventos? ¿Desea ejecutar este código como respuesta a un evento? –

Respuesta

58
var evt = document.createEvent("Event"); 
evt.initEvent("myEvent",true,true); 

// custom param 
evt.foo = "bar"; 

//register 
document.addEventListener("myEvent",myEventHandler,false); 

//invoke 
document.dispatchEvent(evt); 

Aquí es la manera de hacerlo de forma más local, la localización de los oyentes y los editores: http://www.kaizou.org/2010/03/generating-custom-javascript-events/

+6

** Nota: ** El método 'createEvent' está en desuso. Utilice ['event constructors'] (https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent) en su lugar. –

+3

Los constructores de eventos no son compatibles con IE. – Nilpo

+0

Pruebe [dom4] (https://github.com/WebReflection/dom4) si desea usar 'CustomeEvent' en IE. Este es un navegador cruzado _polyfill_ que proporciona interfaces DOM 4 Nivel 4. Con esto puedes usar 'CustomEvent' en IE 8 o superior. – Tsutomu

41

La implementación de eventos personalizados no es difícil. Puedes implementarlo de muchas maneras. Últimamente estoy haciendo de esta manera:

/*************************************************************** 
* 
* Observable 
* 
***************************************************************/ 
var Observable; 
(Observable = function() { 
}).prototype = { 
    listen: function(type, method, scope, context) { 
     var listeners, handlers; 
     if (!(listeners = this.listeners)) { 
      listeners = this.listeners = {}; 
     } 
     if (!(handlers = listeners[type])){ 
      handlers = listeners[type] = []; 
     } 
     scope = (scope ? scope : window); 
     handlers.push({ 
      method: method, 
      scope: scope, 
      context: (context ? context : scope) 
     }); 
    }, 
    fireEvent: function(type, data, context) { 
     var listeners, handlers, i, n, handler, scope; 
     if (!(listeners = this.listeners)) { 
      return; 
     } 
     if (!(handlers = listeners[type])){ 
      return; 
     } 
     for (i = 0, n = handlers.length; i < n; i++){ 
      handler = handlers[i]; 
      if (typeof(context)!=="undefined" && context !== handler.context) continue; 
      if (handler.method.call(
       handler.scope, this, type, data 
      )===false) { 
       return false; 
      } 
     } 
     return true; 
    } 
}; 

El objeto observable puede ser reutilizado y aplicada por cualquier constructor necesita simplemente por mixng el prototipo de observable con el prototipo muy de ese constructor.

para empezar a escuchar, hay que darse de alta en el objeto observable, así:

var obs = new Observable(); 
obs.listen("myEvent", function(observable, eventType, data){ 
    //handle myEvent 
}); 

O si su oyente es un método de un objeto, así:

obs.listen("myEvent", listener.handler, listener); 

Dónde listener es una instancia de un objeto, que implementa el método "handler".

El objeto observable ahora puede llamar a su método fireEvent cada vez que sucede algo que se quiere comunicar a sus oyentes:

this.fireEvent("myEvent", data); 

Cuando los datos es algunos datos que los oyentes Mi encuentran interesante. Lo que sea que pongas allí depende de ti; tú sabes mejor de qué está hecho tu evento personalizado.

El método fireEvent simplemente pasa por todos los oyentes que se registraron para "myEvent" y llama a la función registrada. Si la función devuelve falso, significa que el evento se cancela y el observable no llamará a los otros oyentes. Como resultado, todo el método fireEvent también volverá a funcionar, por lo que el observable sabe que cualquier acción que notificara a sus oyentes debería revertirse.

Quizás esta solución no convenga a todo el mundo, pero he tenido mucho beneficio de esta pieza relativamente simple de código.

+0

¿Dónde se llama this.fireEvent ("myEvent", data) from? Estoy confundido sobre el alcance "este". –

+0

Escribí: "El objeto Observable ahora puede llamar a su método fireEvent". Por lo tanto, esto se refiere a la instancia del objeto observable (o un objeto que se mezcla en sus métodos) –

+0

¿Hay alguna diferencia significativa en el comportamiento/rendimiento entre una solución como la anterior y una que crea, agrega y envía eventos personalizados en el documentar el objeto DOM? – Pappa

9

A partir de aquí:

https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events

// create the event 
var evt = document.createEvent('Event'); 
// define that the event name is `build` 
evt.initEvent('build', true, true); 

// elem is any element 
elem.dispatchEvent(evt); 


// later on.. binding to that event 
// we'll bind to the document for the event delegation style. 
document.addEventListener('build', function(e){ 
    // e.target matches the elem from above 
}, false); 
+3

En la misma página https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events#Creating_events, menciona que esto no es compatible con IE. – phpLearner

2

Aquí es una muy simple (Letra de imprenta/Babelish) implementación:

const simpleEvent = <T extends Function>(context = null) => { 
    let cbs: T[] = []; 
    return { 
     addListener: (cb: T) => { cbs.push(cb); }, 
     removeListener: (cb: T) => { let i = cbs.indexOf(cb); cbs.splice(i, Math.max(i, 0)); }, 
     trigger: (<T> (((...args) => cbs.forEach(cb => cb.apply(context, args))) as any)) 
    }; 
}; 

que lo utilice como esto:

let onMyEvent = simpleEvent(); 
let listener = (test) => { console.log("triggered", test); }; 
onMyEvent.addListener(listener); 
onMyEvent.trigger("hello"); 
onMyEvent.removeListener(listener); 

o en clases como esto

class Example { 
    public onMyEvent = simpleEvent(this); 
} 

Si desea llanura JavaScript que puede transpile usando TypeScript playground.