如何手动触发更改事件 - 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 以常规方式检测到变化一样。
目前,我所做的是实现CompB
的ngOnInit
方法,并通过ViewChild
link在updateItem
方法中调用该方法].故事的另一部分是我的实际来源有像 someArray
这样的对象,我想在每次渲染时重置它们。不过,我不确定重新渲染是否会重置 someArray
。目前,我正在 ngOnInit
方法中重置它们。
所以,我的问题是:如何触发对父对象更深层元素的更改的重新渲染?
谢谢
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 仍会更新] 模板中的 item
。这是因为保留了对该对象的引用。因此要有这种行为:
And afterwards, make the child component i.e. CompB re-rendered as if
angular detected a change in the regular way.
您无需特别执行任何操作,因为您仍会在 DOM 中获得更新。
手动更改检测
您可以插入一个变化检测器并像这样触发它:
@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();
}
}
这会触发对当前组件及其所有子组件的更改检测。
但是,它对你的情况没有任何影响,因为即使 Angular 没有检测到 item
的变化,它 仍然为子 B
组件运行更改检测 并 更新 DOM.
除非你使用ChangeDetectionStrategy.OnPush
。在这种情况下,一种适合您的方法是在 CompB
:
的 ngDoCheck
挂钩中进行手动检查
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();
}
}
}
您可以在以下文章中找到更多信息:
您可以在 CompB 中放置另一个输入,这样当您想要更改 CompA 中项目的属性时,只需更改此输入的值即可。
@Component({
selector: 'compA',
template: template: `<compB [item]=item [trigger]=trigger></compB>`
})
export class CompA {
item:any;
trigger: any;
updateItem():void {
item[name] = "updated name";
trigger = new Object();
}
}
@Component({
selector: 'compB',
template: template: `<p>{{item[name]}}</p>`
})
export class CompB implements OnInit{
@Input() item: any;
@Input() trigger: any;
}
给定以下组件:
@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 以常规方式检测到变化一样。
目前,我所做的是实现CompB
的ngOnInit
方法,并通过ViewChild
link在updateItem
方法中调用该方法].故事的另一部分是我的实际来源有像 someArray
这样的对象,我想在每次渲染时重置它们。不过,我不确定重新渲染是否会重置 someArray
。目前,我正在 ngOnInit
方法中重置它们。
所以,我的问题是:如何触发对父对象更深层元素的更改的重新渲染?
谢谢
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 仍会更新] 模板中的 item
。这是因为保留了对该对象的引用。因此要有这种行为:
And afterwards, make the child component i.e. CompB re-rendered as if angular detected a change in the regular way.
您无需特别执行任何操作,因为您仍会在 DOM 中获得更新。
手动更改检测
您可以插入一个变化检测器并像这样触发它:
@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();
}
}
这会触发对当前组件及其所有子组件的更改检测。
但是,它对你的情况没有任何影响,因为即使 Angular 没有检测到 item
的变化,它 仍然为子 B
组件运行更改检测 并 更新 DOM.
除非你使用ChangeDetectionStrategy.OnPush
。在这种情况下,一种适合您的方法是在 CompB
:
ngDoCheck
挂钩中进行手动检查
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();
}
}
}
您可以在以下文章中找到更多信息:
您可以在 CompB 中放置另一个输入,这样当您想要更改 CompA 中项目的属性时,只需更改此输入的值即可。
@Component({
selector: 'compA',
template: template: `<compB [item]=item [trigger]=trigger></compB>`
})
export class CompA {
item:any;
trigger: any;
updateItem():void {
item[name] = "updated name";
trigger = new Object();
}
}
@Component({
selector: 'compB',
template: template: `<p>{{item[name]}}</p>`
})
export class CompB implements OnInit{
@Input() item: any;
@Input() trigger: any;
}