如何手动触发更改事件 - angular2 [英] How to trigger a change event manually - angular2
问题描述
给定以下组件:
@Component({
selector: 'compA',
template: template: `<compB [item]=item></compB>`
})
export class CompA {
item:any;
updateItem():void {
item[name] = "updated name";
}
}
@Component({
selector: 'compB',
template: template: `<p>{{item[name]}}</p>`
})
export class CompB implements OnInit{
@Input() item: any;
someArray: any[];
ngOnInit():void {
someArray.push("something");
}
}
据我所知,除非完整的 item
对象被更改,否则 angular2 无法识别 item
上的更改.因此,当调用 updateItem
方法时,我想为 item
手动发出更改事件.然后,使子组件,即 CompB
重新渲染,就好像 angular 以常规方式检测到变化一样.
As far as I understood that unless the complete item
object is changed, angular2 does not recognize the changes on item
. Therefore, I'd like to emit a change event manually for item
when the updateItem
method is called. And afterwards, make the child component i.e. CompB
re-rendered as if angular detected a change in the regular way.
目前,我所做的是实现CompB
的ngOnInit
方法,并通过方法在
链接.故事的另一部分是我的实际源有像 updateItem
方法中调用该方法>ViewChildsomeArray
这样的对象,我想在每次渲染中重置它们.不过,我不确定重新渲染是否会重置 someArray
.目前,我正在 ngOnInit
方法中重置它们.
Currently, what I have done is to implement the ngOnInit
method of for CompB
and call that method inside updateItem
method through a ViewChild
link. Another part of the story is that my actual source has objects like someArray
which I'd like to be reset in each render. I'm not sure re-rendering resets someArray
though. Currently, I'm resetting them in the ngOnInit
method.
所以,我的问题是:如何触发重新渲染以更改父对象更深层次的元素?
So, my question is: how do I trigger re-rendering for changes on deeper elements of a parent object?
谢谢
推荐答案
据我所知,除非完整的项目对象是已更改,angular2 无法识别项目上的更改.
As far as I understood that unless the complete item object is changed, angular2 does not recognize the changes on item.
事情并没有那么简单.您必须区分在对象发生变异时触发 ngOnChanges
和子组件的 DOM 更新.Angular 无法识别 item
已更改并且不会触发 ngOnChanges
生命周期钩子,但是如果您引用 的特定属性,DOM 仍会更新模板中的项目
.这是因为保留了对对象的引用.因此有这种行为:
It's not all that straightforward. You have to distinguish between triggering ngOnChanges
when object is mutated and DOM update of the child component. Angular doesn't recognize that item
is changed and doesn't trigger a ngOnChanges
lifecycle hook, but the DOM will still be updated if you reference particular property of the item
in the template. It's because the reference to the object is preserved. Therefore to have this behavior:
然后,使子组件,即 CompB 重新渲染,好像angular 以常规方式检测到变化.
And afterwards, make the child component i.e. CompB re-rendered as if angular detected a change in the regular way.
您不需要做任何特别的事情,因为您仍然会在 DOM 中进行更新.
You don't have to do anything in particular because you will still have update in the DOM.
您可以插入一个变更检测器并像这样触发它:
You can insert a change detector and trigger it like this:
@Component({
selector: 'compA',
template: template: `<compB [item]=item></compB>`
})
export class CompA {
item:any;
constructor(cd: ChangeDetectorRef) {}
updateItem():void {
item[name] = "updated name";
this.cd.detectChanges();
}
}
这会触发当前组件及其所有子组件的更改检测.
This triggers change detection for the current component and all its children.
但是,它不会对你的情况产生任何影响,因为即使 Angular 没有检测到 item
中的变化,它仍然运行变化检测strong> 用于子 B
组件并更新 DOM.
But, it won't have any effect in your case because even though Angular doesn't detect change in item
it still runs change detection for the child B
component and updates the DOM.
除非您使用 ChangeDetectionStrategy.OnPush
.在这种情况下,一种方法是在 CompB
的 ngDoCheck
钩子中进行手动检查:
Unless you use ChangeDetectionStrategy.OnPush
. In this case a way to go for you would be to do a manual check in the ngDoCheck
hook of the CompB
:
import { ChangeDetectorRef } from '@angular/core';
export class CompB implements OnInit{
@Input() item: any;
someArray: any[];
previous;
constructor(cd: ChangeDetectorRef) {}
ngOnInit():void {
this.previous = this.item.name;
someArray.push("something");
}
ngDoCheck() {
if (this.previous !== this.item.name) {
this.cd.detectChanges();
}
}
}
您可以在以下文章中找到更多信息:
You can find more information in the following articles:
这篇关于如何手动触发更改事件 - angular2的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!