我有简单的angular2应用程序。该应用程序只有一个包含ChangeDetectionStrategy.OnPush的组件。 问题是组件永远不会刷新其视图。 数据阵列更新后如何使组件自行刷新? 这里的代码。我使用的是Angular 2.0.0-rc.4。
的index.html
<head>
<title>Angular 2 QuickStart</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<!-- 2. Configure SystemJS -->
<script src="systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>
<body>
<app style="width:100%;height:100%;">Loading...</app>
</body>
main.ts
import { bootstrap } from "@angular/platform-browser-dynamic";
import { AppComponent } from "./app";
bootstrap(AppComponent);
app.ts
import {Component, ComponentRef, ComponentFactory, ViewContainerRef} from "@angular/core";
import {ListComponent} from "./list";
@Component({
selector: "app",
template: `
<div>
<h1>Angular2 - app</h1>
<gm-list></gm-list>
</div>
`,
directives: [ListComponent]
})
export class AppComponent {
}
list.ts
import {Component, Input, NgZone, ChangeDetectionStrategy, ChangeDetectorRef} from "@angular/core";
@Component({
selector: "gm-list",
template: `<div style='width:100%;height:100%;'>
List
<div *ngFor="let item of data" >
<div>
{{ test }}
</div>
<div>
<label class="checkbox">
<input type="checkbox" [(ngModel)]="item.visible"> {{ item.name }}
</label>
</div>
</div>
</div>`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ListComponent {
private _data: any = [];
constructor(private zone: NgZone, private changeDetectorRef: ChangeDetectorRef) {
}
ngOnInit(): void {
var me = this;
setTimeout(function () {
me.data = [
{ id: 1, name: "one", visible: true },
{ id: 2, name: "two", visible: false },
{ id: 3, name: "three", visible: true },
{ id: 4, name: "four", visible: false },
{ id: 5, name: "five", visible: true },
{ id: 6, name: "six", visible: true }
];
}, 3000);
}
@Input() set data(data: any) {
this._data = data;
console.log("databind");
}
get data(): any {
return this._data;
}
get test(): string {
//console.log("test");
return "test";
}
}
答案 0 :(得分:2)
来自https://github.com/angular/angular/issues/4746#issuecomment-150754049
OnPush
仅在输入属性具有时才会触发更改检测 由于更改检测检查而被更改
1)因此,您需要通过changeDetectorRef.markForCheck
手动运行更改,例如:
export class ListComponent {
constructor(private changeDetectorRef: ChangeDetectorRef) {}
ngOnInit(): void {
setTimeout(() => {
this.data = [...];
this.changeDetectorRef.markForCheck();
}, 3000);
}
...
<强> demo plunker 强>
2)如果你更改了父母的输入数据,它将被更新,因为这将触发对孩子的检查( plunker ):
@Component({
selector: 'my-app',
template: `<gm-list [data]="data"></gm-list>`,
directives: [ListComponent]
})
export class App {
data:any[];
constructor() {
setTimeout(() => {
this.data = [...];
}, 3000);
}
}
3)或者您可以通过使用对父组件的引用(或使用EventEmitter
)来运行更新,如下所示:
export class ListComponent {
constructor(@Inject(forwardRef(() => App)) private parent:App) {}
ngOnInit(): void {
setTimeout(() => {
this.parent.data = [...];
}, 3000);
}
}
@Component({
selector: 'my-app',
template: `<gm-list [data]="data"></gm-list>`,
directives: [ListComponent]
})
export class App {
data: any[];
}
<强> plunker 强>
答案 1 :(得分:0)
Angular2尚未稳定。代码可能会在发布中更改。找到了以下解决方案,版本为rc4。
1)添加
changeDetection: ChangeDetectionStrategy.OnPush,
2)组件状态改变后调用
this.changeDetectorRef.markForCheck();
this.changeDetectorRef.detectChanges();