Ich frage mich, ob Sie in TypeScript benutzerdefinierte Ereignisse für Ihre Klassen oder Schnittstellen definieren können?Unterstützt TypeScript Ereignisse in Klassen?
Wie würde das aussehen?
Ich frage mich, ob Sie in TypeScript benutzerdefinierte Ereignisse für Ihre Klassen oder Schnittstellen definieren können?Unterstützt TypeScript Ereignisse in Klassen?
Wie würde das aussehen?
Wie wäre es mit diesem vereinfachten Ereignis, das als Eigenschaft verwendet werden soll? Stärkere Typisierung der besitzenden Klasse und keine Vererbung Bedarf:
interface ILiteEvent<T> {
on(handler: { (data?: T): void }) : void;
off(handler: { (data?: T): void }) : void;
}
class LiteEvent<T> implements ILiteEvent<T> {
private handlers: { (data?: T): void; }[] = [];
public on(handler: { (data?: T): void }) : void {
this.handlers.push(handler);
}
public off(handler: { (data?: T): void }) : void {
this.handlers = this.handlers.filter(h => h !== handler);
}
public trigger(data?: T) {
this.handlers.slice(0).forEach(h => h(data));
}
public expose() : ILiteEvent<T> {
return this;
}
}
wie so verwendet:
class Security{
private readonly onLogin = new LiteEvent<string>();
private readonly onLogout = new LiteEvent<void>();
public get LoggedIn() { return this.onLogin.expose(); }
public get LoggedOut() { return this.onLogout.expose(); }
// ... onLogin.trigger('bob');
}
function Init() {
var security = new Security();
var loggedOut =() => { /* ... */ }
security.LoggedIn.on((username?) => { /* ... */ });
security.LoggedOut.on(loggedOut);
// ...
security.LoggedOut.off(loggedOut);
}
Verbesserungen?
Wenn zwei verschiedene Instanzen dieselbe Methode anhängen, denke ich, dass "aus" dann die inkorrekte entfernen kann. (da Methoden auf dem Prototyp sind, so sind sie die gleiche Instanz für jede Objektinstanz) – Kikaimaru
@Kikaimaru - Ich verstehe nicht. Kannst du es ausarbeiten? –
Wenn Sie einen Handler entfernen möchten, sollten Sie wahrscheinlich einen Verweis auf die Handler-Funktion beibehalten: 'var handler1 = function (data) {alert ('handler1'); }; var handler2 = function (data) {alert ('handler2'); }; var ev = neues Ereignis(); ev.on (handler1); ev.on (handler2); ev.trigger(); ev.off (handler1); ev.Handler; alert ('Invoke round 2'); ev.trigger(); ' – VeeTheSecond
Sie können benutzerdefinierte Ereignisse in TypeScript verwenden. Ich bin nicht sicher genau das, was Sie zu tun versuchen, aber hier ist ein Beispiel:
module Example {
export class ClassWithEvents {
public div: HTMLElement;
constructor (id: string) {
this.div = document.getElementById(id);
// Create the event
var evt = document.createEvent('Event');
evt.initEvent('customevent', true, true);
// Create a listener for the event
var listener = function (e: Event) {
var element = <HTMLElement> e.target;
element.innerHTML = 'hello';
}
// Attach the listener to the event
this.div.addEventListener('customevent', listener);
// Trigger the event
this.div.dispatchEvent(evt);
}
}
}
Wenn Sie schauen, um etwas zu tun spezifischere lass es mich wissen.
Ich denke, Sie fragen, ob eine Klasseninstanz addEventListener() und dispatchEvent() wie ein DOM-Element implementieren kann. Wenn die Klasse kein DOM-Knoten ist, müssten Sie Ihren eigenen Ereignisbus schreiben. Sie würden eine Schnittstelle für eine Klasse definieren, die Ereignisse veröffentlichen kann, und dann die Schnittstelle in Ihren Klassen implementieren. Hier ist ein naives Beispiel;
interface IEventDispatcher{
// maintain a list of listeners
addEventListener(theEvent:string, theHandler:any);
// remove a listener
removeEventListener(theEvent:string, theHandler:any);
// remove all listeners
removeAllListeners(theEvent:string);
// dispatch event to all listeners
dispatchAll(theEvent:string);
// send event to a handler
dispatchEvent(theEvent:string, theHandler:any);
}
class EventDispatcher implement IEventDispatcher {
private _eventHandlers = {};
// maintain a list of listeners
public addEventListener(theEvent:string, theHandler:any) {
this._eventHandlers[theEvent] = this._eventHandlers[theEvent] || [];
this._eventHandlers[theEvent].push(theHandler);
}
// remove a listener
removeEventListener(theEvent:string, theHandler:any) {
// TODO
}
// remove all listeners
removeAllListeners(theEvent:string) {
// TODO
}
// dispatch event to all listeners
dispatchAll(theEvent:string) {
var theHandlers = this._eventHandlers[theEvent];
if(theHandlers) {
for(var i = 0; i < theHandlers.length; i += 1) {
dispatchEvent(theEvent, theHandlers[i]);
}
}
}
// send event to a handler
dispatchEvent(theEvent:string, theHandler:any) {
theHandler(theEvent);
}
}
Diese Lösung ermöglicht es Ihnen, die Parameter in dem Funktionsaufruf direkt zu schreiben, anstatt benötigen alle Parameter in einem Objekt zu wickeln.
interface ISubscription {
(...args: any[]): void;
}
class PubSub<T extends ISubscription> {
protected _subscribed : ISubscriptionItem[] = [];
protected findSubscription(event : T) : ISubscriptionItem {
this._subscribed.forEach((item : ISubscriptionItem) =>{
if (item.func==event)
return item;
});
return null;
}
public sub(applyObject : any,event : T) {
var newItem = this.findSubscription(event);
if (!newItem) {
newItem = {object : applyObject, func : event };
this._subscribed.push(newItem);
this.doChangedEvent();
}
}
public unsub(event : T) {
for (var i=this._subscribed.length-1 ; i>=0; i--) {
if (this._subscribed[i].func==event)
this._subscribed.splice(i,1);
}
this.doChangedEvent();
}
protected doPub(...args: any[]) {
this._subscribed.forEach((item : ISubscriptionItem)=> {
item.func.apply(item.object, args);
})
}
public get pub() : T {
var pubsub=this;
var func= (...args: any[]) => {
pubsub.doPub(args);
}
return <T>func;
}
public get pubAsync() : T {
var pubsub=this;
var func = (...args: any[]) => {
setTimeout(() => {
pubsub.doPub(args);
});
}
return <T>func;
}
public get count() : number {
return this._subscribed.length
}
}
Verbrauch:
interface ITestEvent {
(test : string): void;
}
var onTestEvent = new PubSub<ITestEvent>();
//subscribe to the event
onTestEvent.sub(monitor,(test : string) => {alert("called:"+test)});
//call the event
onTestEvent.pub("test1");
Just Down Abstimmung ohne Erklärung ist weniger nützlich – daslicht
Wenn Sie suchen Sie die folgenden jetzt tun mit dem Standard-Emitter-Muster überprüft Intelli-Sense-Typ zu bekommen:
type DataEventType = "data";
type ErrorEventType = "error";
declare interface IDataStore<TResponse> extends Emitter {
on(name: DataEventType, handler : (data: TResponse) => void);
on(name: ErrorEventType, handler: (error: any) => void);
}
The Strongly Typed Events for TypeScript Projekt (Version 0.3) implementiert 3 Arten von Ereignissen: IEvent<TSender, TArgs>
, ISimpleEvent<TArgs>
und ISignal
. Dies macht es einfacher, die richtige Art von Ereignis für Ihr Projekt zu verwenden. Es verbirgt auch die Dispatch-Methode aus Ihrem Event, da ein gutes Ausblenden von Informationen ausreichen sollte.
Ereignistypen/Schnittstellen - Die Definitionen der Ereignisse:
interface IEventHandler<TSender, TArgs> {
(sender: TSender, args: TArgs): void
}
interface ISimpleEventHandler<TArgs> {
(args: TArgs): void
}
interface ISignalHandler {
(): void;
}
Beispiel - Dieses Beispiel zeigt, wie die drei Arten von Ereignissen mit einer tickenden Uhr durchgeführt werden können:
class Clock {
//implement events as private dispatchers:
private _onTick = new SignalDispatcher();
private _onSequenceTick = new SimpleEventDispatcher<number>();
private _onClockTick = new EventDispatcher<Clock, number>();
private _ticks: number = 0;
constructor(public name: string, timeout: number) {
window.setInterval(() => {
this.Tick();
}, timeout);
}
private Tick(): void {
this._ticks += 1;
//trigger event by calling the dispatch method and provide data
this._onTick.dispatch();
this._onSequenceTick.dispatch(this._ticks);
this._onClockTick.dispatch(this, this._ticks);
}
//expose the events through the interfaces - use the asEvent
//method to prevent exposure of the dispatch method:
public get onTick(): ISignal {
return this._onTick.asEvent();
}
public get onSequenceTick() : ISimpleEvent<number>{
return this._onSequenceTick.asEvent();
}
public get onClockTick(): IEvent<Clock, number> {
return this._onClockTick.asEvent();
}
}
Verwendung - Es kann wie folgt verwendet werden:
let clock = new Clock('Smu', 1000);
//log the ticks to the console
clock.onTick.subscribe(()=> console.log('Tick!'));
//log the sequence parameter to the console
clock.onSequenceTick.subscribe((s) => console.log(`Sequence: ${s}`));
//log the name of the clock and the tick argument to the console
clock.onClockTick.subscribe((c, n) => console.log(`${c.name} ticked ${n} times.`))
Lesen Sie mehr hier: On events, dispatchers and lists (a general explanation of the system)
Tutorials
ich ein paar Tutorials zu diesem Thema geschrieben haben:
danke, sehr nett! – daslicht
Genau das wollte ich dir danken! – ToastyMallows
Check this out: - http://stackoverflow.com/questions/12756423/is-there-an-alias-for-this-in-typescript –