[解決済み] Angular2の変更検出:ネストされたオブジェクトに対してngOnChangesが発生しない
質問
この件について質問するのは初めてではないのですが、以前の質問で答えが見つかりません。私は、あるコンポーネントに次のようなものを入れています。
<div class="col-sm-5">
<laps
[lapsData]="rawLapsData"
[selectedTps]="selectedTps"
(lapsHandler)="lapsHandler($event)">
</laps>
</div>
<map
[lapsData]="rawLapsData"
class="col-sm-7">
</map>
コントローラ内
rawLapsdata
は時々変異します。
で
laps
として出力されます.
HTML
を表形式で表示します。これは
rawLapsdata
が変更されます。
私の
map
コンポーネントは
ngOnChanges
をトリガーとして、GoogleMap上のマーカーを再描画します。問題は
ngOnChanges
を実行しても
rawLapsData
が親で変更されました。どうしたらいいでしょうか。
import {Component, Input, OnInit, OnChanges, SimpleChange} from 'angular2/core';
@Component({
selector: 'map',
templateUrl: './components/edMap/edMap.html',
styleUrls: ['./components/edMap/edMap.css']
})
export class MapCmp implements OnInit, OnChanges {
@Input() lapsData: any;
map: google.maps.Map;
ngOnInit() {
...
}
ngOnChanges(changes: { [propName: string]: SimpleChange }) {
console.log('ngOnChanges = ', changes['lapsData']);
if (this.map) this.drawMarkers();
}
更新しました。
ngOnChanges
は動作しませんが、まるで
lapsData
が更新されています。その中で
ngOnInit
はズーム変更のイベントリスナーで、これも
this.drawmarkers
. ズームを変更すると、確かにマーカが変化しています。つまり、入力データが変更されたときに通知を受け取れないことが唯一の問題なのです。
親の中に、こんな行があります。(周回遅れで変更が反映されるのであって
map
).
this.rawLapsData = deletePoints(this.rawLapsData, this.selectedTps);
そして、以下のことに注意してください。
this.rawLapsData
は、それ自体が大きなjsonオブジェクトの中央へのポインタです。
this.rawLapsData = this.main.data.TrainingCenterDatabase.Activities[0].Activity[0].Lap;
解決方法は?
rawLapsData
は、たとえ配列の内容を変更したとしても (たとえば項目の追加、削除、項目の変更など)、 同じ配列を指し続けます。
変更検出の際、Angularはコンポーネントの入力プロパティに変更がないかチェックする際、(基本的に)以下のように使用します。
===
ダーティチェック用。 配列の場合、これは配列の参照 (のみ) をダーティチェックすることを意味します。 配列の場合は
rawLapsData
配列の参照は変更されません。
ngOnChanges()
は呼び出されない。
2つの解決策が考えられますね。
-
実装する
ngDoCheck()
を作成し、配列の内容が変更されたかどうかを判断するための独自の変更検出ロジックを実行します。 (Lifecycle Hooks のドキュメントには 例 .) -
に新しい配列を代入する。
rawLapsData
配列の内容を変更するたびに 次にngOnChanges()
が呼ばれるのは、配列(の参照)が変更されたように見えるからです。
回答では、別の解決策を考えていましたね。
ここでOPのいくつかのコメントを繰り返す。
私はまだ、どのように
laps
と同等のものを使っているはずです)。ngOnChanges()
であるのに対しmap
はできません。
-
で
laps
コンポーネントの各エントリに対して、コード/テンプレートがループします。lapsData
配列の中身を表示するので、表示されるデータそれぞれにAngularバインディングがあります。 -
Angularがコンポーネントの入力プロパティの変更を検出しない場合でも、(
===
をチェックします) が、それでも (デフォルトでは) すべてのテンプレートバインディングをダーティにチェックします。これらのいずれかが変更されると、AngularはDOMを更新します。 これがあなたが見ているものです。 -
は
maps
コンポーネントは、おそらくそのテンプレートにlapsData
入力プロパティですよね?そうすると、この違いが説明できますね。
なお
lapsData
の両コンポーネントと
rawLapsData
はすべて同じ/1つの配列を指しています。 そのため、Angularが(参照)変更に気づかない場合でも
lapsData
入力プロパティは、すべてのコンポーネントがその1つの配列を共有/参照しているため、配列の内容の変更を取得/確認することができます。 プリミティブ型(文字列、数値、ブール値)のように、Angularがこれらの変更を伝搬する必要はありません。 しかし、プリミティブ型では、値を変更すると、常に
ngOnChanges()
- これは、あなたの回答/解決策で悪用されているものです。
もうお分かりかと思いますが、オブジェクトの入力プロパティは配列の入力プロパティと同じ動作をします。
関連
-
[解決済み] インデックスを属性値とするngFor
-
[解決済み] コンポーネントテンプレートで要素を選択するには?
-
[解決済み] NgModuleにおける宣言、プロバイダ、インポートの違いは何ですか?
-
[解決済み] Angularで変更検知を手動でトリガーする
-
[解決済み] Angularアプリを本番用にバンドルする方法
-
[解決済み] Angular 2のキープレスごとの変更イベント
-
[解決済み] Angular - すべてのリクエストにヘッダを設定する
-
[解決済み] The Angular Compiler requires TypeScript >=3.1.1 and <3.2.0 but 3.2.1 found insteadでエラーが発生しました。
-
[解決済み] Angular 2でシングルトンサービスを作成するには?
-
[解決済み] angular-cli server - デフォルトのポートを指定する方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Angular 2 下へスクロールする(チャット形式)
-
[解決済み] Angular HTMLバインディング
-
[解決済み] インデックスを属性値とするngFor
-
[解決済み] Angularで@Input()の値が変更されたときに検出する方法は?
-
[解決済み】Angular 2 - innerHTML スタイリング
-
[解決済み] Angular 2.0のルーターがブラウザーの再読み込みで動作しない件
-
[解決済み] Angular CLI Error: serveコマンドはAngularプロジェクトで実行する必要がありますが、プロジェクト定義が見つかりませんでした。
-
[解決済み] ナンバーパイプ - Angular 2のパラメータは?
-
[解決済み] Angular 2 http.post()がリクエストを送信しない
-
[解決済み] @angular/material/index.d.ts' はモジュールではありません。