angular - 如何干净地检测Angular中对象的深层变化?
问题描述
在父组件中,我有一个对象(在我的特定情况下,它是 FormBuilder 的 FormGroup 的控件),我将其作为输入传递给子组件。
<my-component form="fb.controls"></my-component>
在子组件中,我定义了输入:
@Input()
form: any;
如果我的子组件的模板引用此对象的属性,则更改检测是自动的。例如:
<div>{{form.myField}}</div>
但是,在某些情况下,我需要处理输入值,然后将其他内容放入模板中。我想避免将逻辑嵌入到模板中。举个简单的例子,这是可行的,但并不漂亮:
<div [class]="form ? form.difficulty ? form.difficulty.value == 'easy' ? 'green' : form.difficulty.value == 'hard' ? 'red' : 'orange' : 'brown' : 'black'"></div>
我发现的替代品都有问题。
- 在模板中调用方法意味着它将被调用无数次
- 向父组件添加任何代码,例如事件发射器或 ngModelChanges,似乎违反了关注点分离,并且比应有的更复杂
- 当只有对象上的一个属性发生变化时,不会调用 ngOnChanges
我希望有一种简单(模板中的代码最少)的方法可以让 Angular 处理更改检测,就像我在模板中显式引用属性一样顺利。
编辑:理想的答案不取决于提供可观察的对象(例如 valueChanges)。Angular 在进行神奇的更改检测时不需要这样做。我想准确地重现 Angular 正在做什么(当视图引用对象上的属性时),但在我的控制器中。
解决方案
具体来说,在您的情况下,当我们处理反应形式时,我将利用valueChanges
它来处理 TS 中的逻辑。只需订阅孩子的 valueChanges 并执行您需要执行的任何逻辑。这是一个非常简单的示例,它查看difficulty
表单控件的值并根据值是否存在显示 ngIf - else 模板easy
:
家长:
form: FormGroup;
constructor(private fb: FormBuilder) {
this.form = this.fb.group({
difficulty: ['']
})
}
然后将表单传递给孩子或您的用例中的任何内容,也许是嵌套的表单组?这里只是传递父表单。
在 child 中,只需监听表单值的变化并将布尔值映射到condition$
observable,true
或者false
取决于difficulty
值:
@Input() form;
condition$: Observable<boolean>;
ngOnInit() {
this.condition$ = this.form.valueChanges.pipe(
// using 'any' just for the sake of the demo... do NOT use any!
map((value: any) => value.difficulty === 'easy')
);
}
那么模板就是:
<div *ngIf="condition$ | async; else elseTemplate">
<p style="color: green">Difficulty is easy!</p>
</div>
<ng-template #elseTemplate>
<p style="color: red">Difficulty is not set as "easy"</p>
</ng-template>
正如一开始已经提到的,这是一个非常简单的例子,但它应该展示我建议你可以做的事情。
如果您将嵌套的表单组传递给子级并且实际上想要监听父级的更改,那么也可以实现,只需parent
在 valueChanges 之前添加:
this.condition$ = this.form.parent.valueChanges.pipe(
// using 'any' just for the sake of the demo... do NOT use any!
map((value: any) => value.difficulty === 'easy')
);
推荐阅读
- javascript - 无法在 url 的查询参数中从 UI 传递空字符串。即使在代码中我已作为“”传递
- amazon-web-services - 禁用 Elastic Beanstalk 的 TRACE/TRACK HTTP 方法
- javascript - 如何使用自定义钩子适当地处理 React 中的字段更改事件?
- python - 带有 Python Selenium 自动化的 Spotify webplayer 帐户检查器
- javascript - 需要帮助的编码初学者
- sql - 为什么 Oracle 在与 NVL 比较的 BETWEEN 中不将 '' 视为 NULL
- drools - 我们可以在 TomcatServer 上安装 Business Central Workbench 7.36 吗?
- r - 子集数据框和创建嵌套列表
- python - Selenium-Python-IE 11 中“元素不再有效”的问题
- python - 为什么 DRF 响应中没有显示“url”