Signals 是一种技术名称,用于 实现细粒度响应式,在前端不同框架中的实现方式各不相同,它的本质还是基于 观察者模式,借助了 gettersetter 来实现响应式更新,并且解决了手动订阅的问题

一个最简单的 Signals 示例

let subscriber = null;
 
function signal(value) {
  const subscribers = new Set();
 
  return {
    get value() {
      if (subscriber) subscribers.add(subscriber);
      return value;
    },
    set value(newValue) {
      value = newValue;
      subscribers.forEach((subscriber) => subscriber());
    },
  };
}
 
function effect(fn) {
  subscriber = fn;
  fn();
  subscriber = null;
}
 
function derived(fn) {
  const derived = signal();
 
  effect(() => {
    derived.value = fn();
  });
 
  return derived;
}
 
let count = signal(0);
let double = derived(() => count.value * 2);
 
effect(() => {
  console.log("count:", count.value);
});
 
effect(() => {
  console.log("count * 2:", double.value);
});
 
count.value = 1;
count.value = 2;

这是一个接近主流框架 Signals 的实现方式了,单独的 Signals 需要配合 Reactions 和衍生状态的处理来使用,才能变得更强大,Reactions 会监听 Signals 的改变,并在其发生更新时重新运行。

Reactions: Effect、Autoruns、Watches、Computed

发展

Angular、Ember、Preact、Qwik、Solid、Svelte、Vue,甚至 Mobx、Tailwind 都已使用 Signals,现在已经有了关于 Signals 的 TC39 提案,未来可能直接在 JavaScript 中使用 Signals。

参考