Typescript-händelsebindning och avbindning
Jag ställde den här frågan för en tid sedan om att delegera jQuery-händelser till händelsehanteringsmetoder i en TypeScript-klass. Svaret var att använda följande mönster
public class LoginDialog {
...
constructor() {
//this.open = this.OpenHandler; //Incorrect way
this.open = (event: Event, ui: DialogUIParams) => { //Correct way
this.OpenHandler(this, event, ui);
};
...
}
public OpenHandler(context: LoginDialog, event: Event, ui: DialogUIParams) {
//Use context as "this"
}
...
}
Men nu är jag i en liknande situation där jag behöver ta bort hanteraren vid någon tidpunkt i framtiden men inte kan på grund av den anonyma funktionen:
public class LoginDialog {
...
constructor() {
this.open = (event: Event, ui: DialogUIParams) => {
this.OpenHandler(this, event, ui);
};
this.close = (event: Event, ui: DialogUIParams) => {
this.CloseHandler(this, event, ui);
}
...
}
public OpenHandler(context: LoginDialog, event: Event, ui: DialogUIParams) {
$(window).on("scroll", () => { context.ScrollHandler(context); });
//$(window).on("scroll", context.ScrollHandler(context)); //Never gets called
//$(window).on("scroll", context.ScrollHandler); //this = window
}
public CloseHandler(context: LoginDialog, event: Event, ui: DialogUIParams) {
$(window).off("scroll", () => { context.ScrollHandler(context); }); //Does not remove
}
public ScrollHandler(context: Interfaces.IBaseDialog) {
context.jQueryDialog.dialog("option", "position", "center");
...
}
...
}
I det här fallet, utan pilsyntaxen i on-bindningen, blir min ResizeOrScrollHandler aldrig kallad, men med den kan jag inte ta bort eventhanteraren i CloseHandler
Svar #1
För att sammanfatta ditt problem, försöker du använda jQuery för att koppla (och koppla bort) en händelse på ett DOM-element, men du vill att händelsehanterarens 'this'-kontext ska peka på klassen som innehåller händelsehanteraren.
Det finns flera sätt att lösa detta.
Först kan du använda jQuery.proxy
class LoginDialog {
public OpenHandler(context: LoginDialog, event: Event, ui: DialogUIParams) {
$(window).on("scroll", $.proxy(context.ScrollHandler, context));
}
public CloseHandler(context: LoginDialog, event: Event, ui: DialogUIParams) {
$(window).off("scroll", context.ScrollHandler);
}
}
Ett annat alternativ skulle vara att använda RxJS, vilket gör att du kan behandla händelser som borttagbara objekt:
var scrollSubscription = $(window)
.onAsObservable("scroll")
.subscribe(() => console.log("this == the containing class!"));
...
// When we're done, just call .dispose.
scrollSubscription.dispose();
Ha kul.
