【问题标题】:Will using Angular Reactive Forms .get() method in template cause unnecessary method calls like a component method?在模板中使用 Angular Reactive Forms .get() 方法会导致不必要的方法调用,如组件方法吗?
【发布时间】:2020-05-26 23:44:33
【问题描述】:

我知道如果我在模板中使用方法调用,它会一遍又一遍地执行(不理想)。我通过结合使用纯管道和记忆方法解决了这个问题。但我也在使用响应式表单,并在我的模板中使用 myFormGroup.get('myFormControl').value 来获取值。这是否会像我的组件中的方法一样重复执行,或者 Angular 是否有防止这种情况发生的策略?一个使用示例是使用 *ngIf 并让条件基于表单的值。

此外,我目前没有遇到任何性能下降,但我希望在使用此应用程序走得太远之前以最好的方式实现这一点(我只是好奇)。

我可以轻松地更新它以直接引用表单对象上的属性,我只是更喜欢方法调用的语法。任何见解都会有所帮助,谢谢!

【问题讨论】:

    标签: javascript angular angular-forms angular2-changedetection


    【解决方案1】:

    当你调用AbstractControl.get(...)时会发生这种情况:

    get(path: Array<string|number>|string): AbstractControl|null {
      return _find(this, path, '.');
    }
    

    Source.

    _find 函数看起来像这样:

    function _find(control: AbstractControl, path: Array<string|number>|string, delimiter: string) {
      if (path == null) return null;
    
      if (!Array.isArray(path)) {
        path = path.split(delimiter);
      }
      if (Array.isArray(path) && path.length === 0) return null;
    
      // Not using Array.reduce here due to a Chrome 80 bug
      // https://bugs.chromium.org/p/chromium/issues/detail?id=1049982
      let controlToFind: AbstractControl|null = control;
      path.forEach((name: string|number) => {
        if (controlToFind instanceof FormGroup) {
          controlToFind = controlToFind.controls.hasOwnProperty(name as string) ?
              controlToFind.controls[name] :
              null;
        } else if (controlToFind instanceof FormArray) {
          controlToFind = controlToFind.at(<number>name) || null;
        } else {
          controlToFind = null;
        }
      });
      return controlToFind;
    }
    

    Source.

    如您所见,您可以获得位于表单控件树更深处的后代。

    例如:

    form.get('a.b.c')
    
    // Or
    
    form.get(['a', 'b', 'c'])
    

    整个逻辑包含一个迭代,因为它从path 迭代每个元素。


    这是否也会像我的组件中的方法一样重复执行

    我会说会的。

    我创建了一个StackBlitz 演示来说明这一点:

    @Component({
      selector: 'my-app',
      template: `
        <form [formGroup]="form">
          <input formControlName="name" type="text">  
        </form>
    
        <hr>
    
        <p>
          Getter value: {{ name.value }}
        </p>
      `,
      styleUrls: ['./app.component.css']
    })
    export class AppComponent {
      form: FormGroup;
      name2: FormControl
    
      get name (): FormControl {
        console.log('getter invoked!')
    
        return this.form.get('name') as FormControl;
      }
    
      constructor (private fb: FormBuilder) { }
    
      ngOnInit () {
        this.form = this.fb.group({ name: '' });
    
        this.name2 = this.form.get('name') as FormControl;
      }
    }
    

    如果您使用的是getter,您应该会看到getter invoked!为您在输入中键入的每个字符记录两次(以及多次调用get 方法)。

    如果您使用{{ form.get('name').value }}AbstractControl.get 方法将被多次调用,超过预期

    您可以通过打开开发工具,输入forms.umd.js 并在path.forEach(function (name) {...} 这一行,在_find 函数的主体内放置一个log breakpoint 来进行测试。

    如果您使用的是this.name2 = this.form.get('name') as FormControl;,您在输入时应该不会看到任何记录。

    在我看来,如果您使用 getter.get()visible 性能下降的可能性较小,但我会采用第三种方法,创建一个单独的property 用于我将在视图中使用的控件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-09
      • 1970-01-01
      • 2012-06-14
      • 2013-03-07
      • 1970-01-01
      • 2016-05-29
      • 2011-01-21
      • 1970-01-01
      相关资源
      最近更新 更多