2012-03-12 20 views
39

Mi chiedevo se qualcuno può aiutarmi a capire esattamente come creare diversi ascoltatori di eventi personalizzati.Listener di eventi personalizzati JavaScript

Non ho un caso specifico di un evento, ma voglio imparare solo in generale come è fatto, quindi posso applicarlo dove è necessario.

Quello che stavo cercando di fare, solo in caso alcune persone potrebbero aver bisogno di conoscere, era:

var position = 0; 

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

Vedere [questa altra domanda] (http://stackoverflow.com/questions/2490825/how-to-trigger-event-in-javascript) – bfavaretto

+0

È possibile utilizzare una libreria come jQuery per creare eventi personalizzati e listener. Dai un'occhiata a http://fuelyourcoding.com/jquery-custom-events-the-will-rock-your-world/ e http://api.jquery.com/trigger/ –

+11

Come è correlato il codice che hai postato gestione degli eventi? Vuoi eseguire questo codice come risposta a un evento? –

risposta

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); 

Ecco il modo per farlo più a livello locale, individuando gli ascoltatori e gli editori: http://www.kaizou.org/2010/03/generating-custom-javascript-events/

+6

** Nota: ** Il metodo 'createEvent' è deprecato. Utilizza invece ['costruttori di eventi'] (https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent). –

+3

I costruttori di eventi non sono supportati in IE. – Nilpo

+0

Prova [dom4] (https://github.com/WebReflection/dom4) se vuoi usare 'CustomeEvent' su IE. Si tratta di un _polyfill_ cross browser che fornisce interfacce DOM 4 livello 4. Con questo puoi usare 'CustomEvent' su IE 8 o successivo. – Tsutomu

41

Implementare eventi personalizzati non è difficile. Puoi implementarlo in molti modi. Ultimamente mi sto facendo in questo modo:

/*************************************************************** 
* 
* 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; 
    } 
}; 

L'oggetto Observable può essere riutilizzato e applicato da qualunque costruttore ne ha bisogno semplicemente mixng il prototipo del Observable con il prototipo di quel costruttore.

Per iniziare l'ascolto, è necessario registrarsi con l'oggetto osservabile, in questo modo:

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

O se il vostro ascoltatore è un metodo di un oggetto, in questo modo:

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

Dove ascoltatore è un'istanza di un oggetto, che implementa il metodo "gestore".

L'oggetto Observable ora può chiamare il suo metodo fireEvent ogni volta che succede qualcosa che si vuole comunicare ai suoi ascoltatori:

this.fireEvent("myEvent", data); 

cui i dati sono alcuni dati che gli ascoltatori la mia trovano interessante. Qualunque cosa tu abbia messo lì dipende da te - sai meglio di cosa è composto il tuo evento personalizzato.

Il metodo fireEvent passa semplicemente attraverso tutti gli ascoltatori registrati per "myEvent" e chiama la funzione registrata. Se la funzione restituisce false, significa che l'evento è annullato e l'osservabile non chiama gli altri ascoltatori. Di conseguenza, l'intero metodo fireEvent tornerà fasullo, quindi l'osservabile sa che qualsiasi azione che stava notificando ai suoi ascoltatori dovrebbe essere ripristinata.

Forse questa soluzione non soddisfa tutti, ma ho avuto molto beneficio da questo pezzo di codice relativamente semplice.

+0

Dove si chiama this.fireEvent ("myEvent", data) da? Sono confuso riguardo alla "portata". –

+0

Ho scritto: "L'oggetto Observable può ora chiamare il suo metodo fireEvent". Quindi, questo si riferisce all'istanza dell'oggetto osservabile (o di un oggetto che si mescola nei suoi metodi) –

+0

C'è qualche differenza significativa nel comportamento/prestazioni tra una soluzione come quella sopra e una che crea, aggiunge e invia eventi personalizzati sul documento DOM oggetto? – Pappa

9

Da qui:

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

Nella stessa pagina https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events#Creating_events si afferma che questo non è supportato in IE. – phpLearner

2

Qui è davvero un semplice (dattiloscritto/Babelish) implementazione:

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)) 
    }; 
}; 

si utilizza in questo modo:

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

o in classi come questo

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

Se volete pianura JavaScript è possibile transpile utilizzando TypeScript playground.