在模板中使用 Angular Reactive Forms .get() 方法会导致像组件方法一样不必要的方法调用吗?

MrU*_*ill 7 javascript angular2-changedetection angular angular-forms

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

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

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

And*_*tej 7

这就是您调用时发生的情况AbstractControl.get(...)

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

来源

_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;
}
Run Code Online (Sandbox Code Playgroud)

来源

正如您所注意到的,您可以获得位于表单控件树中更深处的后代。

例如:

form.get('a.b.c')

// Or

form.get(['a', 'b', 'c'])
Run Code Online (Sandbox Code Playgroud)

整个逻辑涉及到一个迭代,因为它迭代了来自 的每个元素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;
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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