導入
レッスン11のサービスやレッスン10の配列操作は、値を書き換えたらAngularが自動で画面を更新してくれる「変更検知」という仕組みの上に成り立っていました。近年のAngularは、この仕組みをもっと明示的で軽量にする signal() という新しい状態管理を用意しています。
説明
signal(初期値) で作った値は、関数として呼ぶと現在の値が読めます(count())。.set(値) で置き換え、.update(fn) で今の値をもとに書き換えます。他のsignalから自動で計算される値は computed()、signalが変わるたびに実行したい処理は effect() で書きます。
@Component({
selector: 'app-root',
standalone: true,
template: `
<h2>Signals で買い物カゴ</h2>
<p>個数: {{ count() }} 個</p>
<p>合計金額: {{ total() }} 円</p>
<button (click)="increment()">+1</button>
<button (click)="decrement()">-1</button>
<button (click)="reset()">リセット</button>
`,
})
class AppComponent {
price = 100;
count = signal(0);
total = computed(() => this.count() * this.price);
constructor() {
effect(() => {
console.log('個数が変わりました:', this.count());
});
}
increment(): void {
this.count.update((n) => n + 1);
}
decrement(): void {
this.count.update((n) => Math.max(0, n - 1));
}
reset(): void {
this.count.set(0);
}
}
signal(0)… 「監視できる値の箱」を作ります。テンプレートやcomputed/effectの中でcount()と関数として呼ぶと、その時点の値が読めます。computed(() => …)… 他のsignalから自動で計算される値。countが変わるたびにtotalも自動で再計算されます。effect(() => …)… signalが変わるたびに実行される副作用。ここでは変化のたびにconsole.logしています(下の「コンソール」欄で確認できます)。.set(値)/.update(fn)… signalの値を書き換える2つの方法。- 普通のプロパティ(
count: number = 0のような書き方)と違い、signalは「誰が読んでいるか」をAngularが正確に把握できるため、より効率よく画面更新できます。
やってみよう
priceを書き換えて、totalが連動して変わることを確認しましょう。effectの中身を「合計金額が◯◯円になりました」のようなログに変えてみましょう。- コンソール欄で、ボタンを押すたびに
effectが実行されていることを確かめましょう。