Angular 2+ 组件的双向绑定

Two Way Binding on an Angular 2+ Component

我有一个 Ionic 应用程序,我在其中创建了一个组件来显示对象的一些数据。我的问题是,当我更新托管组件的父级中的数据时,组件中的数据不会更新:

我的-card.component.ts

@Component({
    selector: 'my-card',
    templateUrl: './my-card.html'
})
export class MyCard {
    @Input('item') public item: any;
    @Output() itemChange = new EventEmitter();
    constructor() {

    }

    ngOnInit() {
        // I do an ajax call here and populate more fields in the item.
        this.getMoreData().subscribe(data => {
            if (data.item){
                this.item = data.item;
            }
            this.itemChange.emit(this.item);
        });
    }
}

我的-card.html

<div class="comment-wrapper" *ngFor="let subitem of item.subitems">
    {{subitem.title}}
</div>

在父级中我使用这样的组件:

<my-card [(item)]="item"></my-card>

以及父级的 ts 文件:

@IonicPage()
@Component({
    selector: 'page-one',
    templateUrl: 'one.html',
})
export class OnePage {
    public item = null;
    constructor(public navCtrl: NavController, public navParams: NavParams) {
        this.item = {id:1, subitems:[]};
    }

    addSubItem():void{
        // AJAX call to save the new item to DB and return the new subitem.
        this.addNewSubItem().subscribe(data => {
            let newSubItem = data.item;
            this.item.subitems.push(newSubItem);
        }
    }
}

因此,当我调用 addSubItem() 函数时,它不会更新组件并且 ngFor 循环仍然不会显示任何内容。

如果 getMoreData 方法 returns 是一个可观察对象,则此代码需要如下所示:

ngOnInit() {
    // I do an ajax call here and populate more fields in the item.
    this.getMoreData().subscribe(
        updatedItem => this.item = updatedItem
    );
}

订阅导致异步操作执行,returns 一个可观察对象。当数据从异步操作返回时,它会执行提供的回调函数并将项目分配给返回的项目。

您使用 @Input() 装饰器将项目声明为:

 @Input('item') public item: any;

但是你在上面使用了two-way绑定:

<my-card [(item)]="item"></my-card>

如果只是输入,应该是

<my-card [item]="item"></my-card>

现在,如果您调用 addSubItem(),它应该会显示新添加的项目。

    this.item = this.getMoreData();

如果您将 getMoreData() 放入您的卡片组件中,则没有任何意义,因为您想使用通过 @Input()

传递的项目

您的组件交互有点不对劲。查看 Angular 文档 (https://angular.io/guide/component-interaction). Specifically, using ngOnChanges (https://angular.io/guide/component-interaction#intercept-input-property-changes-with-ngonchanges) or use a service to subscribe and monitor changes between the parent and the child (https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service) 上的指南。

您在发出 api 请求时破坏了 object 引用。您正在分配新值,即覆盖您从 parent 获得的输入值,并且 object 不再指向相同的 object,而是 item你的 child 是一个完全不同的 object。如你所愿two-way-binding,我们可以利用Output:

Child:

import { EventEmitter, Output } from '@angular/core';

// ..

@Input() item: any;
@Output() itemChange = new EventEmitter();

ngOnInit() {
  // I do an ajax call here and populate more fields in the item.
  this.getMoreData(item.id).subscribe(data => {
    this.item = data;
    // 'recreate' the object reference
    this.itemChange.emit(this.item)
  });
}

现在我们再次拥有相同的 object 引用,无论您在 parent 中做什么,都会反映在 child 中。