2012-03-12 16 views
39

Zastanawiam się, czy ktoś może mi pomóc zrozumieć, jak dokładnie tworzyć różne niestandardowe detektory zdarzeń.JavaScript niestandardowy odbiornik zdarzeń

Nie mam konkretnego przypadku zdarzenia, ale chcę się uczyć w zasadzie jak to zrobić, więc mogę zastosować go tam, gdzie jest to potrzebne.

czego szukałem do zrobienia, nie rozczarować niektórzy ludzie mogą wiedzieć, było:

var position = 0; 

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

Zobacz [to inne pytanie] (http://stackoverflow.com/questions/2490825/how-to-trigger-event-in-javascript) – bfavaretto

+0

Możesz użyć biblioteki, takiej jak jQuery, do tworzenia niestandardowych zdarzeń i detektorów. Zajrzyj na http://fuelyourcoding.com/jquery-custom-events-they-will-rock-your-world/ i http://api.jquery.com/trigger/ –

+11

W jaki sposób opublikowany przez Ciebie kod dotyczy Obsługa zdarzeń? Czy chcesz uruchomić ten kod jako odpowiedź na wydarzenie? –

Odpowiedz

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

Oto sposób to zrobić bardziej lokalnie, identyfikowanie słuchaczy i wydawców: http://www.kaizou.org/2010/03/generating-custom-javascript-events/

+6

** Uwaga: ** Metoda 'createEvent' jest przestarzała. Zamiast tego używaj ['konstruktorów zdarzeń'] (https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent). –

+3

Konstruktory zdarzeń nie są obsługiwane w IE. – Nilpo

+0

Spróbuj [dom4] (https://github.com/WebReflection/dom4), jeśli chcesz używać "CustomeEvent" na IE. Jest to przeglądarka internetowa _polyfill_, która udostępnia interfejsy DOM 4 poziomu 4. Dzięki temu możesz użyć "CustomEvent" na IE 8 lub nowszym. – Tsutomu

41

Wdrażanie niestandardowych zdarzeń nie jest trudne. Możesz go wdrożyć na wiele sposobów. Ostatnio robię to tak:

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

obserwowalnym obiekt może być ponownie wykorzystane i stosowane przez co konstruktor musi go po prostu przez mixng prototyp Obserwowalne z protoype tego konstruktora.

aby rozpocząć odtwarzanie, trzeba zarejestrować się do zaobserwowania przedmiotu, tak jak poniżej:

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

Albo jeśli słuchacz jest metodą obiektu, tak jak poniżej:

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

Gdzie detektor jest instancją obiektu, który implementuje metodę "handler".

obserwowalnym obiekt może teraz wywołać jego metodę fireEvent gdy coś się dzieje, że chce przekazać swoich słuchaczy:

this.fireEvent("myEvent", data); 

gdzie dane są niektóre dane, które słuchacze moich znaleźć interesujące. Wszystko, co włożysz, zależy od Ciebie - wiesz najlepiej, z czego składa się twoje niestandardowe wydarzenie.

Metoda fireEvent po prostu przechodzi przez wszystkie detektory zarejestrowane dla "myEvent" i wywołuje zarejestrowaną funkcję. Jeśli funkcja zwróci wartość false, oznacza to, że zdarzenie zostało anulowane, a obserwowalne nie wywoła innych detektorów. W rezultacie cała metoda fireEvent również powróci, więc obserwujący wie, że jakiekolwiek działanie powiadamiające jej słuchaczy powinno zostać wycofane.

Być może to rozwiązanie nie pasuje do wszystkich, ale ja, ve, mieliśmy wiele korzyści z tego stosunkowo prostego kawałka kodu.

+0

Skąd wywołujesz to .fireEvent ("myEvent", dane) z? Jestem zdezorientowany co do "tego" zakresu. –

+0

Napisałem: "Observable obiekt może teraz wywołać jego metodę fireEvent". Tak więc odnosi się to do instancji obserwowalnego obiektu (lub obiektu, który miesza się w jego metodach). –

+0

Czy istnieje jakaś istotna różnica w zachowaniu/wydajności między rozwiązaniem takim jak powyższe i tym, które tworzy, dodaje i wysyła zdarzenia niestandardowe dokument DOM obiektu? – Pappa

9

stąd:

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

Na tej samej stronie https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events#Creating_events wspomina, że ​​nie jest to obsługiwane w IE. – phpLearner

2

Tutaj jest naprawdę proste (maszynopis/Babelish) implementacja:

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

go używać tak:

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

Albo w klasach jak to

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

Jeśli chcesz zwykły JavaScript można transpile go za pomocą TypeScript playground.

Powiązane problemy