如何纠正功能范围?

时间:2019-07-08 11:21:51

标签: javascript angular

在我的模板中,我使用了一些呈现步进器的第三方组件,您可以在其中进行导航:

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

所以我想我可以使用固定的this指针生成一个新函数:

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

[stepChangeCallback]="getStepChangeCallbackFunction()"

这确实有效,但是,我看到内存消耗不断增加,并且该网站最终会导致浏览器崩溃,因为它不断生成新的功能副本。

还有其他解决方法吗?

2 个答案:

答案 0 :(得分:6)

对我来说,最好的选择是使用instance arrow function

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

您可以使用[stepChangeCallback]="stepChangeCallback.bind(this)",但它还会在每次更改检测运行时创建一个新功能。

另一种选择是在构造函数中绑定this

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

   stepChangeCallback(selectedStep) { 
     ...
   }
}

答案 1 :(得分:2)

除了@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>