Подтвердить что ты не робот

Typescript функция обработчика событий для поля типа события - неправильный контекст

Это интерфейс jquery из jquery.d.ts:

export interface IDialogEvent extends DialogEvent {
    (event: Event, ui: DialogUIParams): void;
}

Это мой пользовательский интерфейс, имитирующий частичную функциональность интерфейса DialogOptions jquery.d.ts:

export interface IDialogOptions {
    open: IDialogEvent;
}

export class DialogClass implements IDialogOptions { 

    //Dialog options
    public open: IDialogEvent;

    //Class related fields
    public someField: any;
    public dialogEl: JQuery;

    constructor() { 
        this.open = this.OpenHandler;
        this.dialogEl = $("<div></div>").dialog(this); 
        //Passing "this" initializes the dialog by mapping relevant class fields
        //to the dialog "option" object, in this case the only "relevant" field is "open".
    }

    public OpenHandler(event: Event, ui: DialogUIParams) { 
        var value = this.someField; //BAD. "this" is not type BaseClass
    }

    public NonEventHandlerMethod() { 
        var value = this.someField; //GOOD. "this" is type BaseClass
    }  
}

var dialog = new DialogClass();
dialog.dialogEl.dialog("open"); 

Последняя строка запускает OpenHandler(), но внутри нее this не является типом BaseDialog (в отличие от NonEventHandlerMethod).

Причина, по которой мне нужна функция обработчика событий для поля параметров диалога и причина, по которой я не могу просто сделать это:

 export class DialogClass implements IDialogOptions { 
     ...
      constructor() { 
          this.open = () => {
                //event handling logic
          };
          ...
      }
      ...
 }        

заключается в том, что мне нужно добавить дополнительную логику обработки открытых событий в классы, расширяющие DialogClass, и нет никакого различия между этим сообщением и супермассером... существует только дифференциация между this.function() и super.function():

 export class LoginDialog extends DialogClass { 
     ...
      constructor() { 
          this.open = this.OpenHandler;
          ...
      }

      public OpenHandler(event: Event, ui: DialogUIParams) { 
           super.OpenHandler(); //Base handling logic

           //Additional handling logic
      } 
      ...
 } 

Я думаю, что это может быть ошибка, потому что

   export class DialogClass implements IDialogOptions { 
     ...
      constructor() { 
          this.open = () => {
                var test = this.someField;  //Correct context
          };
          ...
      }
      ...
   }  

и вызов метода напрямую:

   var dialog = new DialogClass();
   dialog.OpenHandler();  //Correct context when called directly
   //Note: I haven't actually tested this persay but this function is no different
   //than any other functionso a direct call should certainly not be problem.
4b9b3361

Ответ 1

TypeScript следует обычным условным обозначениям JavaScript, поэтому this будет зависеть от контекста. Если у вас есть метод для класса, который запускается на основе события, this будет целью события. Когда вы вызываете метод в классе, this будет классом.

Если вы хотите обойти это, вы можете воспользоваться тем, как JavaScript просматривает цепочку областей видимости, предоставляя this псевдоним...

Вот один из способов сделать это:

this.open = () => { this.OpenHandler(this); };

Синтаксис функции-стрелки создает и псевдоним _this в JavaScript.

public OpenHandler(context: DialogClass, event: Event, ui: DialogUIParams) { 
    var value = context.someField;
}

Мы принимаем умную псевдониму версию this в качестве параметра, а context.someField должно иметь значение, которое мы имеем после.