在模板中使用 Angular Reactive Forms .get() 方法会导致不必要的方法调用,如组件方法吗? [英] Will using Angular Reactive Forms .get() method in template cause unnecessary method calls like a component method?

查看:24
本文介绍了在模板中使用 Angular Reactive Forms .get() 方法会导致不必要的方法调用,如组件方法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

此外,我目前没有遇到任何性能下降,但我想以最好的方式实现这一点,然后再用这个应用程序走得太远(我只是好奇).

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

解决方案

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

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

来源.

_find 函数看起来像这样:

function _find(control: AbstractControl, path: Array|string, delimiter: string) {如果(路径==空)返回空;if (!Array.isArray(path)) {路径 = path.split(delimiter);}if (Array.isArray(path) && path.length === 0) return null;//由于 Chrome 80 错误,此处不使用 Array.reduce//https://bugs.chromium.org/p/chromium/issues/detail?id=1049982让 controlToFind: AbstractControl|null = control;path.forEach((name: string|number) => {if (controlToFind instanceof FormGroup) {controlToFind = controlToFind.controls.hasOwnProperty(name as string) ?controlToFind.controls[name] :空值;} else if (controlToFind instanceof FormArray) {controlToFind = controlToFind.at(name) ||空值;} 别的 {controlToFind = null;}});返回 controlToFind;}

来源.>

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

例如:

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

整个逻辑涉及一个迭代,因为它迭代了来自path的每个元素.

<小时><块引用>

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

我会说会的.

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

@Component({选择器:'我的应用',模板:`<form [formGroup]="form"><input formControlName="name" type="text"></表单><小时><p>获取值:{{ name.value }}</p>`,styleUrls: ['./app.component.css']})导出类 AppComponent {表格:表格组;名称2:表单控件获取名称():FormControl {console.log('getter 被调用!')返回 this.form.get('name') 作为 FormControl;}构造函数(私有 fb:FormBuilder){}ngOnInit () {this.form = this.fb.group({ name: '' });this.name2 = this.form.get('name') as FormControl;}}

如果您使用 getter,您应该看到 getter 被调用! 为您在输入中输入的每个字符记录两次(以及 getcode> 方法也被多次调用).

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

您可以通过打开开发工具,输入 forms.umd.js 并在该行 path.forEach(function (name) {...},在 _find 函数体内.

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

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

I know that if I use a method call in a template it will get executed over and over (not ideal). I have solved that by using a combination of pure pipes and memoized methods. But I am also using reactive forms and in my template using the myFormGroup.get('myFormControl').value to get the values. Will this too get executed repeatedly like the method in my component or does Angular have a strategy in place to prevent this? A usage example is using *ngIf and having the conditional be based on a value of the form.

Also, I am not experiencing any performance degradation currently, but I would like to implement this in the best way possible before getting too far down the road with this application (and am just curious).

I can easily update it to reference the properties on the form object directly, I just prefer the syntax of the method call. Any insight would be helpful, thanks!

解决方案

This is what happens when you call AbstractControl.get(...):

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

Source.

And the _find function looks like this:

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.

As you noticed, you can get descendants that reside deeper in the form control tree.

For instance:

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

// Or

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

This whole logic involes an iteration, because it's iterating over each element from path.


Will this too get executed repeatedly like the method in my component

I'd say it will.

I've created a StackBlitz demo to illustrate this:

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

If you're using a getter, you should see getter invoked! logged twice for each character you type in the input(and the get method called multiple times as well).

If you're using {{ form.get('name').value }}, the AbstractControl.get method will be called multiple times, more than expected.

You can test this by opening the dev tools, typing forms.umd.js and placing a log breakpoint at this line path.forEach(function (name) {...}, inside _find function's body.

And if you're using this.name2 = this.form.get('name') as FormControl;, you should see nothing logged as you're typing.

In my opinion, it's less likely that the visible performance will decrease if you're using a getter or .get(), but I'd go with the third approach, creating a separate property for the control I'll be using in the view.

这篇关于在模板中使用 Angular Reactive Forms .get() 方法会导致不必要的方法调用,如组件方法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆