Hello,大家好,我是 Sunday。
今天咱们来看 TC39 的新提案 Signals 信号。该提案主要应用在 状态管理 相关的场景下,可以结合目前状态管理工具(Vuex、Pinia、Redux、MobX 或者是单纯的 ref(Vue3 中声明响应式数据的方案) 等)实现全新的解决方案。
目前犹大也在 vue 官网中提供了 Connection to Signals(与信号 (signal) 的联系) 的概念,并提到 Signal 的重要性
那么下面咱们就来看看这个 Signal 到底是个什么东西。
什么是 TC39 以及标准提案流程
想要了解 Signal 咱们先来看看 TC39 提案!
TC39 提案是指由ECMAScript(JavaScript的标准)技术委员会TC39(Technical Committee 39)提出的标准改进建议。TC39负责JavaScript语言的演进和标准化工作。一个提案从最初的想法到最终成为标准,需要经过多个阶段的审核和修改。以下是提案的各个阶段:
- Strawman(稻草人阶段):这个阶段是一个初步的想法,可能没有具体的实现细节,目的是引发讨论和反馈。
- Proposal(提案阶段):在这个阶段,提案需要有一个详细的规范描述,并且至少有一个实现。提案会在TC39会议上讨论,若获得足够支持,则进入下一阶段。
- Draft(草案阶段):在这个阶段,提案已经有了详细的规范文档,并且需要有至少两个不同的实现。提案在这个阶段需要进行更广泛的测试和反馈。
- Candidate(候选阶段):提案在这个阶段被认为是稳定的,并且所有可能的改进建议已经纳入。规范文档在这个阶段已经基本定型,剩下的工作主要是验证和确保没有遗漏的错误。
- Finished(完成阶段):提案在这个阶段成为ECMAScript标准的一部分,将被正式发布。此时,提案的内容已经被完全采纳和记录。
为什么需要 Signals(信号)
要开发复杂的用户界面 (UI),JavaScript 应用程序开发人员需要以高效的方式 存储、计算、使状态失效、同步并将状态推送到应用程序的视图层。UI 通常不仅仅涉及管理简单的值,还经常涉及渲染计算状态,而计算状态依赖于其他值或状态的复杂树,而这些值或状态本身也是计算出来的。
Signals 的目标是提供用于管理此类应用程序状态的基础设施,以便开发人员可以专注于业务逻辑,而不是这些重复的细节。
咱们来看一个例子(基于 preact):
import { signal } from "@preact/signals";
const count = signal(0);
// 通过访问.Value读取信号的值:
console.log(count.value); // 0
// 更新信号的值
count.value += 1;
// 访问值也必须要有 .value
console.log(count.value); // 1
通过以上代码我们可以看出来 Signals 与 vue 中的 ref 使用是有些类似的。它们都需要通过一个方法进行初始化,同时访问的时候需要 .value
Signals 与框架的关联
除了我们刚才看到的 preact 之外,还有很多的框架也实现了 Signals。比如:
- Solid
- Angular
- Qwik
从根本上说,Signals 是与 Vue 中的 ref 相同的响应性基础类型(再前面我们也看到了类似的代码例子)。**Signals是一个在访问时跟踪依赖、在变更时触发副作用的值容器。
这种基于响应性基础类型的范式在前端领域并不是一个特别新的概念:它可以追溯到十多年前的 Knockout observables 和 Meteor Tracker 等实现。
Vue 的选项式 API 和 React 的状态管理库 MobX 也是基于同样的原则,只不过将基础类型这部分隐藏在了对象属性背后。