2016-07-22 81 views
0

我有简单的angular2应用程序。该应用程序只有一个包含ChangeDetectionStrategy.OnPush的组件。 问题是组件从不刷新它的视图。 如何在更新数据数组后更新自己的组件? 这里的代码。我正在使用Angular 2.0.0-rc.4。如何使用changeDetection:ChangeDetectionStrategy.OnPush in angular2

的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"; 
    } 
} 

回答

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

0

Angular2还不稳定。代码可能会在发行版中更改。以下解决方案适用于rc4版本。

1)添加

changeDetection: ChangeDetectionStrategy.OnPush, 

2)成分状态改变调用后

this.changeDetectorRef.markForCheck(); 
this.changeDetectorRef.detectChanges();