web-dev-qa-db-ja.com

変更イベントを手動でトリガーする方法-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の変更を認識しないことを私が理解している限り、したがって、itemメソッドが呼び出されたときに、updateItemの変更イベントを手動で発行したいと思います。そしてその後、angularが通常の方法で変更を検出したかのように、子コンポーネント、つまりCompBを再レンダリングします。

現在、私が行っているのは、ngOnInitCompBメソッドを実装し、updateItemメソッド内でViewChildリンクを介してそのメソッドを呼び出すことです。ストーリーのもう1つの部分は、実際のソースにsomeArrayのようなオブジェクトがあり、レンダリングごとにリセットしたいということです。ただし、再レンダリングによってリセットが確実に行われるかどうかはわかりませんsomeArray。現在、ngOnInitメソッドでそれらをリセットしています。

だから、私の質問は、親オブジェクトのより深い要素の変更に対して再レンダリングをトリガーするにはどうすればよいですか?

ありがとう

18
suat

完全なアイテムオブジェクトが変更されない限り、angular2はアイテムの変更を認識しないことを理解している限り。

それはそれほど簡単ではありません。オブジェクトが変更されたときのngOnChangesのトリガーと、子コンポーネントのDOM更新を区別する必要があります。 Angularは、itemが変更されたことを認識せず、ngOnChangesライフサイクルフックをトリガーしませんが、テンプレートでitemの特定のプロパティを参照すると、DOMは引き続き更新されます。これは、オブジェクトへの参照は保持されます。したがって、この動作をさせるには:

その後、子コンポーネントを作成します。つまり、angularが通常の方法で変更を検出したかのように、CompBを再レンダリングします。

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 itの変更を検出しませんまだ変更検出を実行します =子のBコンポーネントおよびDOMを更新の場合。

nlessを使用しますChangeDetectionStrategy.OnPush。この場合、あなたのために行く方法は、ngDoCheckCompBフックで手動チェックを行うことでしょう:

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();
      }
    }
}

詳細については、次の記事をご覧ください。

15
Maxim Koretskyi

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;
}
0
Behzad Jafari