Angular @Input値変更検知方法
Angularで@Input()値が変更されたときを検知する方法の解説(日本語)
Angularにおける@Input()
デコレータは、コンポーネントに外部から値を渡すための手段です。この値が変更されたときに、コンポーネント内で適切な処理を行うためには、変更を検知する必要があります。
ngOnChangesライフサイクルフック
最も一般的な方法は、ngOnChanges
ライフサイクルフックを使用することです。このフックは、コンポーネントの入力プロパティが変更されたときに自動的に呼び出されます。
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
@Component({
selector: 'my-component',
template: `
<p>Value: {{ value }}</p>
`
})
export class MyComponent implements OnChanges {
@Input() value: any;
ngOnChanges(changes: SimpleChanges) {
if (changes['value'].currentValue !== changes['value'].previousValue) {
// 値が変更されたときの処理
console.log('Value has changed:', changes['value'].currentValue);
}
}
}
- これらの値を比較して、変更が実際に発生したかどうかを確認できます。
changes['value'].currentValue
は現在の値、changes['value'].previousValue
は以前の値です。ngOnChanges
メソッドは、変更されたプロパティに関する情報をSimpleChanges
オブジェクトとして受け取ります。
ChangeDetectorRefを使用する
ChangeDetectorRef
サービスを使用すると、手動で変更検出をトリガーすることができます。
import { Component, Input, ChangeDetectorRef } from '@angular/core';
@Component({
selector: 'my-component',
template: `
<p>Value: {{ value }}</p>
`
})
export class MyComponent {
@Input() value: any;
constructor(private changeDetectorRef: ChangeDetectorRef) {}
ngOnChanges() {
// 値が変更されたときに手動で変更検出をトリガー
this.changeDetectorRef.detectChanges();
}
}
detectChanges()
メソッドを呼び出すことで、コンポーネントの変更検出サイクルを開始します。
@Input()デコレータのonChangeオプション
Angular 11以降では、@Input()
デコレータにonChange
オプションを使用して、カスタム変更検出ロジックを提供できます。
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
@Component({
selector: 'my-component',
template: `
<p>Value: {{ value }}</p>
`
})
export class MyComponent implements OnChanges {
@Input() value: any;
@Input() set value(newValue: any) {
// カスタム変更検出ロジック
if (newValue !== this._value) {
this._value = newValue;
// 値が変更されたときの処理
console.log('Value has changed:', newValue);
}
}
private _value: any;
}
value
プロパティのセッター関数内で、カスタム変更検出ロジックを実装します。
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
@Component({
selector: 'my-component',
template: `
<p>Value: {{ value }}</p>
`
})
export class MyComponent implements OnChanges {
@Input() value: any;
ngOnChanges(changes: SimpleChanges) {
if (changes['value'].currentValue !== changes['value'].previousValue) {
// 値が変更されたときの処理
console.log('Value has changed:', changes['value'].currentValue);
}
}
}
- 解説
changes
オブジェクトには、変更されたプロパティに関する情報が含まれています。currentValue
は現在の値、previousValue
は以前の値です。
import { Component, Input, ChangeDetectorRef } from '@angular/core';
@Component({
selector: 'my-component',
template: `
<p>Value: {{ value }}</p>
`
})
export class MyComponent {
@Input() value: any;
constructor(private changeDetectorRef: ChangeDetectorRef) {}
ngOnChanges() {
// 値が変更されたときに手動で変更検出をトリガー
this.changeDetectorRef.detectChanges();
}
}
- 解説
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
@Component({
selector: 'my-component',
template: `
<p>Value: {{ value }}</p>
`
})
export class MyComponent implements OnChanges {
@Input() value: any;
@Input() set value(newValue: any) {
// カスタム変更検出ロジック
if (newValue !== this._value) {
this._value = newValue;
// 値が変更されたときの処理
console.log('Value has changed:', newValue);
}
}
private _value: any;
}
- 解説
SimpleChangeオブジェクトの比較
ngOnChanges
ライフサイクルフックで受け取るSimpleChanges
オブジェクトを直接比較することで、変更を検知することもできます。
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
@Component({
selector: 'my-component',
template: `
<p>Value: {{ value }}</p>
`
})
export class MyComponent implements OnChanges {
@Input() value: any;
ngOnChanges(changes: SimpleChanges) {
if (changes['value'] && changes['value'].previousValue !== changes['value'].currentValue) {
// 値が変更されたときの処理
console.log('Value has changed:', changes['value'].currentValue);
}
}
}
- 解説
Object.isを使用する
Object.is
関数を使用して、値の厳密な比較を行うこともできます。
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
@Component({
selector: 'my-component',
template: `
<p>Value: {{ value }}</p>
`
})
export class MyComponent implements OnChanges {
@Input() value: any;
ngOnChanges(changes: SimpleChanges) {
if (changes['value'] && !Object.is(changes['value'].previousValue, changes['value'].currentValue)) {
// 値が変更されたときの処理
console.log('Value has changed:', changes['value'].currentValue);
}
}
}
- 解説
rxjsのdistinctUntilChangedパイプ
rxjs
のdistinctUntilChanged
パイプを使用して、値が変更されたときにのみイベントを発行することもできます。
import { Component, Input, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
import { distinctUntilChanged } from 'rxjs/operators';
@Component({
selector: 'my-component',
template: `
<p>Value: {{ value }}</p>
`
})
export class MyComponent implements OnInit {
@Input() value: any;
private valueSubject = new Subject<any>();
private value$ = this.valueSubject.asObservable().pipe(distinctUntilChanged());
ngOnInit() {
this.value$.subscribe(newValue => {
// 値が変更されたときの処理
console.log('Value has changed:', newValue);
});
}
ngOnChanges() {
this.valueSubject.next(this.value);
}
}
- 解説
valueSubject
を使用して、値の変更をイベントとして発行します。
angular angular2-changedetection angular-decorator