Signal(信号)是一种存储应用程序状态的形式,类似于React中的useState()。但是,Signal有一些关键差异。Vue、Preact、Solid和Qwik等流行的JavaScript框架都支持Signal。Signal并不新鲜,它之前就存在于像Knockout这样的框架中。然而,近年来,通过巧妙的编译器技巧和与JSX的深度集成,它的开发者体验得到了极大的改善,这使得它非常干净且易于使用。让我们来看看Signal的优势,以及为什么它是前端框架的未来!什么是信号?Signal和State之间的主要区别在于Signal返回一个getter和一个setter,而非响应式系统返回一个值和一个setter。注意:有些响应式系统同时返回一个getter/setter,有些则返回两个单独的引用,但思路是一样的。Signal的优势State混淆了两个独立的概念:StateReference:对状态的引用。StateValue:存储在状态ref/store中的实际值。那么为什么返回一个getter比返回一个值更好呢?因为通过返回一个getter,可以将状态引用的传递与状态值的读取分开。我们以这段SolidJS代码为例:createSignal():分配StateStorage并将其初始化为0。getCount:对可以传递的状态的引用。getCount():获取状态值。上面解释了Signal和normalState之间的区别。那么Signal有什么优势呢?信号是反应性的,这意味着它需要跟踪谁对状态感兴趣(订阅者),如果状态发生变化,则通知订阅者状态变化。为了具有反应性,信号必须收集对其值感兴趣的人。它通过观察在什么情况下调用状态获取器来获取此信息。通过从getter获取值,告诉Signal该位置对该值感兴趣。如果值发生变化,则需要调用getter来创建订阅。这就是传递状态getter而不是状态值很重要的原因。传递状态值不会向Signal提供有关该值实际使用位置的任何信息。这就是为什么状态引用和状态值之间的区别在Signal中如此重要。为了比较,这里是Qwik中的相同示例。请注意,(getter/setter)已被替换为具有.value属性(代表getter/setter)的单个对象。虽然语法不同,但内部工作原理是相同的。单击按钮并增加值时,框架只需要将文本节点从0更新为1。它可以这样做是因为在模板的初始渲染期间,Signal已经知道只能访问count.value通过文本节点。所以它知道如果count的值发生变化,它只需要更新文本节点而不是其他任何地方。useState()的缺点我们来看看在React中如何使用useState()以及它的缺点。React的useState()返回一个状态值。这意味着useState()不知道组件或应用程序内部如何使用状态值。因此,一旦通过调用setCount()通知React状态更改,React就不知道页面的哪一部分发生了更改,因此必须重新渲染整个组件,这在计算上是昂贵的。useRef()不渲染React的useRef()类似于useSignal(),但不会导致页面重新渲染。下面的示例看起来与useSignal()非常相似,但它不起作用。useRef()的使用与useSignal()完全相同,用于传递对状态的引用而不是状态本身。但是,useRef()缺少订阅跟踪和通知。在基于信号的框架中,useSignal()和useRef()是相同的。useSignal()可以实现useRef()加上订阅跟踪的功能,进一步简化了框架的API。内置的useMemo()Signal被最低限度地记忆化,因为它几乎没有工作要做。让我们看一个有两个计数器和两个子组件的例子:这里只有两个Display组件之一的文本节点会被更新。未更新的文本节点将永远不会在初始渲染后打印。#初始渲染输出
