Как исправить область действия функции? - PullRequest
2 голосов
/ 08 июля 2019

В моем шаблоне я использую какой-то сторонний компонент, который рендерит степпер, где вы можете перемещаться между шагами:

<my-stepper step="{{ currentStep }}" steps-label="steps"
   [stepChangeCallback]="stepChangeCallback">
   <my-stepper-step>First</my-stepper-step>
   <my-stepper-step>First</my-stepper-step>
   <my-stepper-step>First</my-stepper-step>
</my-stepper>

и

export class HeaderComponent implements OnInit {
   currentStep = 0;

   stepChangeCallback(selectedStep) { 
     this.currentStep = selectedStep; // PROBLEM: this does not point to HeaderComponent
   }
}

Так что я подумал, что мог бы просто сгенерировать новую функцию с фиксированным указателем:

getStepChangeCallbackFunction() {
   return this.stepChangeCallback.bind(this);
}

и [stepChangeCallback]="getStepChangeCallbackFunction()"

Это работает, однако, я вижу, что потребление памяти постоянно растет и что веб-сайт в конечном итоге приведет к сбою браузера, поскольку он постоянно генерирует новые копии функций.

Есть ли другое решение?

Ответы [ 2 ]

6 голосов
/ 08 июля 2019

Что касается меня, лучшим вариантом здесь является использование функции стрелки экземпляра :

stepChangeCallback = (selectedStep) => { 
  ...
}

Вы можете использовать [stepChangeCallback]="stepChangeCallback.bind(this)", но это также создаст новую функцию при каждом обнаружении измененийrun.

Другой вариант - связать this в конструкторе.

export class HeaderComponent implements OnInit {   
  constructor() {
    this.stepChangeCallback = this.stepChangeCallback.bind(this);
  }

   stepChangeCallback(selectedStep) { 
     ...
   }
}
2 голосов
/ 08 июля 2019

В дополнение к ответу @yurzui, я думаю, есть анти-шаблон с my-stepper компонентом.Вместо того, чтобы принимать функцию как вход и вызывать ее внутри, вы можете отправить событие с my-stepper на stepChange.

Вот как вы можете это сделать

@Component({
  selector: 'my-stepper',
  ...
})
export class MyStepperComponent {

  @Input()
  stepChangeCallback; // <- currently you have this.

  @Output() // instead of an input, just define this output.
  stepChange: EventEmitter<any> = new EventEmitter(); 


  onStepChange(selectedStep) {
    // currently, you call this.stepChangeCallback and you need to check if it is defined
    if (this.stepChangeCallback) {
      this.stepChangeCallback(selectedStep);
    }

    // instead you can simply emit an event and do not care about who is listening
    this.stepChange.emit(selectedStep);
  } 
}

Тогда ваш шаблон будет выглядеть следующим образом, и вам не нужно будет также использовать функцию стрелки

<my-stepper step="{{ currentStep }}" steps-label="steps"
   (stepChange)="stepChangeCallback($event)">
   <my-stepper-step>First</my-stepper-step>
   <my-stepper-step>First</my-stepper-step>
   <my-stepper-step>First</my-stepper-step>
</my-stepper>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...