Signal in Angular

Signal in Angular

Angular 16+ 开始引入了 Signal,按照官方的说法是为了替代 zone。当第一眼看到signal,我曾遐想翩翩,立刻想到了 Vue 中的Ref,又想到了mobx。然而,Angular 官方给的例子居然用了一个count,一个计数的例子。它居然不用对象来举例。我脑补了好多细节。但是当真的尝试却发现,我想多了。那么简单一句话,Angular 里面的 Signal 究竟是个啥,有啥用处? 先给结论

结论

  • signal 除了使用的时候多了个方法调用signaldata(),除此之外,它跟它里面的对象是同一个对象。没有任何区别。
const orignData = { a: 1, b: { c: 1 } };
const data = signal(orignData);
data() === originData; // true
  • signal 对象跟原始对象有什么区别
    唯一的区别是当 signal 对象发送变化的时候,这些使用signaldata() 会被 angularmarkForCheck, 注意不是detachChange()
  • signal 对象中的update() vs set()有啥区别
    这两个方法没有任何区别。纯粹是两个不同的用法
  • 既然 signal 对象跟原始对象是一样的,那可以直接修改原始对象吗?
    你当然可以修改原始对象。如果 signal 中的对象引用没有发生变化,修改也有可能被反应到 UI 上。但是有限制
    • 对于 OnPush 的组件,如果直接修改对象,不会被 angular 标记,如果使用update/set并且 signal 对象被认为发生改变,则会被标记
  • 如何认为 signal 对象发生了变化?
    signal(initalvalue:any,options?:{equal:((pre,cur)=>boolean)}),如果没有提供第二个参数,那么默认是通过===来判断是否发生改变。所以,在使用update/set方法的时候一定要返回一个新的对象{...obj},否则 signal 对象会认为没有发生变化。也就是你跟修改原始对象的效果是一致的。
  • 如何看待 computed 对象?
    它其实就是一个对于依赖的 signal 的对象的推导(derive)。当最后一次执行 computed 函数体时,用到的 signal 对象发生变化,computed 的值才会被重新计算,否则,不会被计算。
  • 那如何看待 signal input 呢。
    我认为它就是一个 signal 的桥架语法糖。将 signal 对象的链路通过 input 连起来。如果没有它,你得通过一些不正常的方式来传递 signal 对象。例如,hack 的方式我没有试,也不知道是否合法,但从 js 语法来说是合法的。
// parent

<child [hackSignal]="signal1"  [signalInput]="signal2()"></child>

signal1=signal(1);
signal2=signal(2);

// child component
<div>{{hackSignal().xxx}}</div>
<div>{{signalInput().xxx}}</div>

@Input()
hackSignal:WritableSignal<T>();

signalInput=input.required<T>();

Angular 的 signal 跟 mobx 或者 Vue 比,不是一个量级的。我原以为,它使用了跟他们类似的代理,功能平分秋色,然而,真的没有他自己吹的那样。

posted @ 2024-03-07 22:38  kongshu  阅读(30)  评论(0编辑  收藏  举报