在模板中使用 Angular Reactive Forms .get() 方法会导致不必要的方法调用,例如组件方法吗?
Will using Angular Reactive Forms .get() method in template cause unnecessary method calls like a component method?
我知道如果我在模板中使用方法调用,它将被反复执行(不理想)。我通过结合使用纯管道和记忆方法解决了这个问题。但我也使用反应形式,并在我的模板中使用 myFormGroup.get('myFormControl').value 来获取值。这是否也会像我的组件中的方法一样重复执行,或者 Angular 是否有适当的策略来防止这种情况发生?一个用法示例是使用 *ngIf 并使条件基于表单的值。
此外,我目前没有遇到任何性能下降,但我想在这个应用程序走得太远之前以尽可能最好的方式实现它(我只是好奇)。
我可以轻松地更新它以直接引用表单对象上的属性,我只是更喜欢方法调用的语法。任何见解都会有所帮助,谢谢!
这就是你调用 AbstractControl.get(...)
时发生的情况:
get(path: Array<string|number>|string): AbstractControl|null {
return _find(this, path, '.');
}
_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;
}
如您所见,您可以获得驻留在表单控件树中更深处的后代。
例如:
form.get('a.b.c')
// Or
form.get(['a', 'b', 'c'])
整个逻辑涉及迭代,因为它迭代path
.
中的每个元素
Will this too get executed repeatedly like the method in my component
我会说会的。
我创建了一个 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
。
我知道如果我在模板中使用方法调用,它将被反复执行(不理想)。我通过结合使用纯管道和记忆方法解决了这个问题。但我也使用反应形式,并在我的模板中使用 myFormGroup.get('myFormControl').value 来获取值。这是否也会像我的组件中的方法一样重复执行,或者 Angular 是否有适当的策略来防止这种情况发生?一个用法示例是使用 *ngIf 并使条件基于表单的值。
此外,我目前没有遇到任何性能下降,但我想在这个应用程序走得太远之前以尽可能最好的方式实现它(我只是好奇)。
我可以轻松地更新它以直接引用表单对象上的属性,我只是更喜欢方法调用的语法。任何见解都会有所帮助,谢谢!
这就是你调用 AbstractControl.get(...)
时发生的情况:
get(path: Array<string|number>|string): AbstractControl|null {
return _find(this, path, '.');
}
_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;
}
如您所见,您可以获得驻留在表单控件树中更深处的后代。
例如:
form.get('a.b.c')
// Or
form.get(['a', 'b', 'c'])
整个逻辑涉及迭代,因为它迭代path
.
Will this too get executed repeatedly like the method in my component
我会说会的。
我创建了一个 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
。