角度信号

想象一下,你和朋友在一家人很多的咖啡馆里。每当你点的咖啡准备好时,柜台上方的灯就会闪烁——这是信号!你不需要一直询问咖啡​​是否准备好了;灯光会立即告诉你。

它们就像信使一样,当数据发生变化时通知您的应用程序,以便一切都无缝更新,而无需您不断检查。

**信号**是一种反应式状态管理机制,它提供了一种直观的方式来管理和跟踪状态变化,同时通过消除手动订阅、区域绑定或复杂状态管理库的需要来提高性能。

*

  • 声明式状态管理:信号创建可观察的值,当依赖项发生变化时自动更新。
  • 细粒度反应性:更新是本地化的,这意味着只有依赖于信号的组件或模板才会重新渲染。
  • 简单:与 RxJS 等其他反应式范例相比,样板最少。
  • **我们如何使用信号?**

    1.创建一个具有初始值的信号。

    // import signal to use
    import { signal } from "@angular/core";
    
    // define a signal with intial value
    const _counter = signal(0);

    2.读取信号值。

    _counter()

    3.改变值。

    _counter.set(1);

    4.通过登录来更改值

    _counter.update((value) => {
       if(value == 0) return 0;
    
       return value - 1;
    });

    5.衍生信号根据其他信号计算值;这将根据当前信号创建一个新的信号。

    const doubleCounter = computed(() => _counter() * 2);

    6.创建可观察的信号。

    const rxSignal = fromObservable(of(1, 2, 3));

    7.根据信号创建可观察对象。

    const obs$ = toObservable(rxSignal);
    obs$.subscribe(value => console.log(value));
  • 要定义只读信号,您可以使用计算信号将信号定义为只读
  • // both are readonly
    _counter: Signal = signal(0);
    _doubleCount: Signal = computed(() => this._counter() * 2);
  • 要定义可写信号,可以使用默认信号或 WritableSignal
  • // both are writable
    _counter = signal(0); // default is writable
    _counter: WritableSignal = signal(0);

    现在我们来看一个反例:

    它有两个组件(一个用于查看,另一个用于增加/减少)和一个服务来管理我们的信号。

    1.柜台服务管理我们的信号。

    我们有三个功能:

  • *getCounter:* 读取信号值。
  • *增量:* 增加信号值。
  • *减少:* 减少信号值并应用条件。
  • import { signal } from "@angular/core";
    
    export class CounterService {
        private _counter = signal(0);
    
        getCounter() {
            return this._counter();
        }
    
        increment() {
            this._counter.update((value) => value + 1);
        }
    
        decrement() {
            this._counter.update((value) => {
                if(value == 0) return 0;
    
                return value - 1;
            });
        }
    }

    2.使用计数器服务并增加/减少信号值的控制组件。

    export class CounterControlsComponent {
      constructor(public counterService: CounterService){}
    }
    
    
  • 使用计数器服务读取和显示信号值的视图组件。
  • export class CounterViewComponent {
      constructor(public counterService: CounterService){}
    }

    Counter : {{counterService.getCounter()}}

    您应该看到这样的视图,并且当您在值为 0 时单击减少时,它不会执行任何操作,只会显示 0

    Image description

    **概括**

  • 使用信号来表示本地化和组件级状态。
  • 优先使用计算信号来获取派生状态,而不是重复逻辑。
  • 处理流或外部可观察对象时与 RxJS 结合。