Typescript olay bağlama ve bağını çözme


Bir süre önce bir Typescript sınıfında jquery olaylarını olay işleyici yöntemlerine devretme hakkında bu soruyu sormuştum. Cevap, aşağıdaki deseni kullanmaktı

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"
     } 
     ...
 } 

Ancak, şimdi ben de gelecekte bir noktada işleyiciyi kaldırmam gereken benzer bir durumdayım ama anonim fonksiyon nedeniyle bunu yapamıyorum:

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

Bu durumda, on bağlamasında ok sözdizimi olmadan, ResizeOrScrollHandler hiçbir zaman çağrılmıyor, ancak ok sözdizimi ile CloseHandler'da olay işleyiciyi kaldıramıyorum.

Cevap #1

Probleminizi özetlemek gerekirse, bir DOM öğesinde bir olayı bağlamak (ve çözmek) için jQuery kullanmaya çalışıyorsunuz, ancak olay işleyicisinin 'this' bağlamının olay işleyiciyi içeren sınıfa işaret etmesini istiyorsunuz.

Bunu çözmenin birden fazla yolu vardır.

İlk olarak, jQuery.proxy kullanabilirsiniz

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

Diğer bir seçenek, olayları kullanılabilir nesneler gibi işlemeye izin veren RxJS'i kullanmak olabilir:

var scrollSubscription = $(window)
     .onAsObservable("scroll")
     .subscribe(() => console.log("this == the containing class!"));
...
// When we're done, just call .dispose.
scrollSubscription.dispose();

İyi eğlenceler.

İlgili makaleler