Angular Signals represent a revolutionary approach to state management and reactivity in Angular applications. This comprehensive guide will walk you through everything you need to know about Signals, from basic concepts to advanced implementations.
Signals are a new primitive introduced in Angular 16 that provide a way to handle reactive state management. They are special wrappers around values that notify interested consumers when those values change.
import { signal } from '@angular/core'; // Creating a simple signal const count = signal(0); // Reading signal value console.log(count()); // Output: 0 // Updating signal value count.set(1);
import { Component, signal } from '@angular/core'; @Component({ selector: 'app-counter', template: ` <div> <p>Count: {{ count() }}</p> <button (click)="increment()">Increment</button> </div> ` }) export class CounterComponent { count = signal(0); increment() { this.count.set(this.count() + 1); } }
const name = signal('John'); name.set('Jane');
const counter = signal(0); counter.update(value => value + 1);
const user = signal({ name: 'John', age: 25 }); user.mutate(value => { value.age = 26; });
Computed signals derive their value from other signals automatically:
import { signal, computed } from '@angular/core'; const price = signal(100); const quantity = signal(2); const total = computed(() => price() * quantity()); console.log(total()); // Output: 200
Effects allow you to perform side effects when signals change:
import { signal, effect } from '@angular/core'; const message = signal('Hello'); effect(() => { console.log(`Message changed to: ${message()}`); }); message.set('Hi'); // Logs: "Message changed to: Hi"
interface Product { id: number; name: string; price: number; } @Component({ selector: 'app-shopping-cart', template: ` <div> <h2>Shopping Cart</h2> <div *ngFor="let item of cartItems()"> {{ item.name }} - ${{ item.price }} </div> <p>Total: ${{ cartTotal() }}</p> </div> ` }) export class ShoppingCartComponent { cartItems = signal<Product[]>([]); cartTotal = computed(() => this.cartItems().reduce((total, item) => total + item.price, 0) ); addToCart(product: Product) { this.cartItems.update(items => [...items, product]); } removeFromCart(productId: number) { this.cartItems.update(items => items.filter(item => item.id !== productId) ); } }
@Component({ selector: 'app-user-form', template: ` <form (submit)="handleSubmit($event)"> <input [value]="formData().name" (input)="updateName($event)" placeholder="Name" > <input [value]="formData().email" (input)="updateEmail($event)" placeholder="Email" > <button type="submit">Submit</button> </form> ` }) export class UserFormComponent { formData = signal({ name: '', email: '' }); updateName(event: Event) { const input = event.target as HTMLInputElement; this.formData.update(data => ({ ...data, name: input.value })); } updateEmail(event: Event) { const input = event.target as HTMLInputElement; this.formData.update(data => ({ ...data, email: input.value })); } handleSubmit(event: Event) { event.preventDefault(); console.log('Form submitted:', this.formData()); } }
// Good practice const userProfile = signal<UserProfile | null>(null); // Better practice with type safety interface UserProfile { name: string; email: string; } const userProfile = signal<UserProfile>({ name: '', email: '' });
Performance Optimization
Error Handling
import { signal } from '@angular/core'; // Creating a simple signal const count = signal(0); // Reading signal value console.log(count()); // Output: 0 // Updating signal value count.set(1);
import { Component, signal } from '@angular/core'; @Component({ selector: 'app-counter', template: ` <div> <p>Count: {{ count() }}</p> <button (click)="increment()">Increment</button> </div> ` }) export class CounterComponent { count = signal(0); increment() { this.count.set(this.count() + 1); } }
const name = signal('John'); name.set('Jane');
Q: What's the difference between Signals and BehaviorSubject?
A: Signals are simpler, more performant, and integrated directly into Angular's change detection. BehaviorSubjects are RxJS observables that require manual subscription management.
Q: Can I use Signals with NgRx?
A: Yes, Signals can complement NgRx for local component state while NgRx handles global application state.
Q: Do Signals replace traditional property binding?
A: No, Signals are an additional tool. Use them when you need reactive state management, but traditional property binding is still valid for simpler cases.
Q: Are Signals available in older Angular versions?
A: Signals were introduced in Angular 16. For older versions, you'll need to use alternatives like RxJS observables.
Angular Signals provide a powerful and efficient way to handle reactive state management in your applications. By following the examples and best practices outlined in this guide, you'll be well-equipped to implement Signals in your own projects. Remember to start simple and gradually incorporate more advanced patterns as your needs grow.
The key to mastering Signals is practice and understanding their reactive nature. Start by implementing basic examples, then progress to more complex scenarios as you become comfortable with the concepts.
The above is the detailed content of From Basics to Advanced: Mastering Angular Signals Step-by-Step. For more information, please follow other related articles on the PHP Chinese website!