手写自己的响应式(Signals)状态管理库

最近,前端空间因对细粒度反应性的新发现而爆炸式增长,这是一种通过使用三种主要原语构建反应性用户界面的风格:信号(signals)、效果(effects)和备忘录(memos)。 最近,我们看到了 Angular,preact 和 Qwik 等框架为其现有框架增加 Signals。当然,Solidjs,我的首选框架和创作者 Ryan Carniato,最近在前端框架的信号中引起了人们的欢迎。

什么是 Signals ?

信号 是持有 订阅列表 的事件发射器。他们在价值变化时通知订阅者。

为什么创建自己的 Signals ?

既然各个框架或库已经支持 Signals,为什么要创建自己的 Signals ? 好吧,实际上,这主要是一种学习体验!

基础知识

对于基本的响应式系统,我们将创建两个原语:createSignalcreateEffect。还有一个原语 createMemo,但在基础知识里不是必需。

让我们继续在 JavaScript 中创建 CreateSignal 的外壳:

JSX

要分解下:

  1. 我们将初始信号值存储在 value 变量;
  2. 创建访问函数 read ,在闭包中返回 signal 的值;
  3. 创建 setter 函数,更新当前 signal 的值;
  4. 返回一个数组,包含以上两个函数。

到目前为止,只是用 let 声明了可变变量,有什么响应性可言?单纯就 signals 而言,它只是个变量,只有和其他原语(像 Effects)使用,才显示出它的价值。

记住,signal 包含订阅列表,这些订阅来自 createEffect, 它将回调函数作为输入函数,并将其设置为全局侦听器,并通过信号读取。代码如下:

JSX

在这里,我们将回调函数赋值给 currentListener,然后调用回调函数。所以,在执行回调函数的时候,回调函数内的 signals 也被调用。接下来,我们需要回到 createSignal, 调整它以将 CurrentListener 添加到订阅列表中,并在 signal 改变时执行回调函数。

JSX

现在,通过跟踪自己闭包内的订阅,effects 内的 signals 的作用自动得到跟踪,并在 signals 改变时重新调用。

完整代码如下:

JSX
JSX

使用 signals

Code Playground

© 2025 Wonder|沪ICP备2022006836号-1