速来报名!AICon北京站鸿蒙专场~ 了解详情
写点什么

备受 Vue、Angular 和 React 青睐的 Signals 演进史

  • 2023-04-10
    北京
  • 本文字数:3519 字

    阅读完需:约 12 分钟

备受Vue、Angular和React青睐的Signals演进史

最近,在前端领域,围绕着“Signals”这个词,有一些热烈的讨论。不管是Preact还是Angular,似乎都在讨论该话题。

 

但它们并不是什么新东西。如果我们将其追溯到上个世纪 60 年代的研究,那么这就更算不上新鲜的事物了。它的基础采用了与第一个电子表格和硬件描述语言(如 Verilog 和 VHDL)相同的模型。

 

即便是在 JavaScript 中,从声明式 JavaScript 框架诞生开始,我们就拥有这种理念了。随着时间的推移,它们有了不同的名字,并且在这些年里不断流行了起来。现在,它又重新出现了,这是一个很好的时机,我们可以对它是什么以及为何需要它进行更多的介绍。

 

免责声明:我是 SolidJS 的作者。本文从我的角度介绍了演进的过程。尽管文中没有提及,但是Elm SignalsEmber的计算属性Meteor都是很值得称道的。

 

如果你还不清楚 Signals 是什么以及它是如何运行的,请参阅我的这篇对细粒度反应性(Fine-Grained Reactivity)的介绍。

起初的蛮荒时代

 

有时候,我们会惊讶地发现,很多参与者在完全相同的时间形成了类似的方案。在声明式 JavaScript 框架的起步阶段,有三个方案在三个月内陆续发布,它们分别是Knockout.js(2010 年 7 月)、Backbone.js(2010 年 10 月)和Angular.js(2010 年 10 月)。

 

Angular 的脏值检查、Backbone 的模型驱动重渲染以及 Knockout 的细粒度更新,虽然它们彼此间有些差异,但是最终都成为了我们今天管理 state 和更新 DOM 的基础。

 

Knockout.js 对本文的主题特别重要,因为它们的细粒度更新是建立在所谓的“Signals”的基础之上的。他们最初引入了两个概念,分别为 observable(状态)和 computed(副作用),但是在接下来的几年中,他们在前端语言中引入了第三个概念 pureComputed(衍生状态)。

 

const count = ko.observable(0);

const doubleCount = ko.pureComputed(() => count() * 2);

// 每当doubleCount更新时,打印日志记录ko.computed(() => console.log(doubleCount()))
复制代码

狂野时代



在这个时代,服务器端开发的 MVC 和过去几年从 jQuery 中学到的模式进行了融合,形成了新的模式。其中,最常见的一个模式叫做数据绑定,Angular.js 和 Knockout.js 都具有该模式,不过实现方式略有不同。

 

数据绑定的概念是,state(状态)应该被关联(attached)到 view tree(视图树)的一个特定部分上。借助这种方式,能够实现的一种强大功能叫做双向绑定。所以,我们可以让状态更新 DOM,反过来,DOM 事件会自动更新状态,所有的这一切均是以一种简单的声明方式实现的。

 

但是,滥用这种力量最终会作茧自缚。我们构建应用的时候,对其缺乏足够深入的了解。在 Angular 中,如果不知道什么内容发生变化,就会对整个树进行脏值检查,而向上传播会导致它多次发生。在 Knockout 中,很难跟踪变化的路径,因为你会在 DOM 上走来走去,出现循环也是司空见惯的。

 

React出现的时候,我们已经准备好逃离这一切了,对我个人来说,是Jing Chen的演讲,让我稳住了阵脚。

 

00:00 / 00:00
    1.0x
    • 3.0x
    • 2.5x
    • 2.0x
    • 1.5x
    • 1.25x
    • 1.0x
    • 0.75x
    • 0.5x
    网页全屏
    全屏
    00:00


    自由时刻



    接下来,就是对 React 的采用。有些人依然喜欢反应式模型,因为 React 对状态管理没有自己的偏好,所以完全可以将两者结合起来。

     

    Mobservable(2015)就是这样的方案。但是,相对于与 React 的集成,它还带来了一些新的内容。它强调一致性和顺畅(glitch-free)的传播。也就是说,对于任何给定的变更,系统的每个部分仅运行一次,而且以适当的顺序同步运行。

     

    为了实现这一点,它使用了一种推-拉(push-pull)混合的系统来替换先前方案中基于推送的反应性。变更的通知会被推送出去,但是衍生状态的执行会推迟到读取它的地方。

     


    为了更好地理解 Mobservable 的原始方式,请参阅 Michel Westrate 的“Becoming Fully Reactive: An in Depth Explanation of Mobservable”一文。

     

    虽然在很大程度上,这个细节会被 React 重新渲染读取变更的组件所掩盖,但是,这是使系统实现可调试和一致性的关键步骤。在接下来的几年里,随着算法的不断完善,我们会看到一种趋势,那就是更多基于拉取的语义

     

    征服泄露的观察者



    细粒度反应性是四人组(Gang of Four)观察者模式的变种。虽然观察者模式是一个强大的同步模式,但是它也有一个典型的问题。一个 Signal 会保持对所有订阅者的强引用,所以长期存活的 Signal 会保留所有的订阅,除非进行手动处置。

     

    这种记录方式在大量使用时会变得很复杂,尤其是在涉及嵌套的时候。在处理分支逻辑和树的时候嵌套很常见的,就像在构建 UI 视图时的那样。

     

    有一个鲜为人知的库,叫做S.js(2013)提供了答案。S 是独立于其他大多数解决方案而开发的,它更直接地以数字电路作为模型,所有的状态变化都在时钟周期内进行。S 将其状态基元称为“Signals”。尽管它不是第一个使用该名字的,但它是我们今天使用该术语的起源。

     

    更为重要的是,它引入了反应式所有权的概念。所有者会收集所有的子反应式作用域,并在所有者处置(disposal)自身或重新执行时,管理子反应式作用域的处置。反应式图会从一个根所有者开始,然后每个节点均作为它所拥有的后代。这个所有者模式不仅对处置过程很有用处,而且在反应式图中,建立了一种提供者/消费者(Provider/Consumer)上下文的机制。

     

    调度



    Vue(2014)也为我们今天的发展做出了巨大的贡献。除了在优化一致一致性方面与 MobX 的节奏保持一致之外,Vue 从一开始就将细粒度反应性作为其核心。

     

    虽然 Vue 和 React 都使用了虚拟 DOM,但是 Vue 的反应性得到了最好的支持,这意味着它是与框架一起研发的,首先是作为内部机制,为其 Options API 提供支持,在过去的几年中,它成为了 Composition API(2020)的前沿和核心。

     

    Vue 将推送/拉取向前推进了一步,能够调度任务何时会完成。默认情况下,Vue 会收集所有的变更,但是下一个微任务在处理作用(effect)队列之前不会处理它们。

     

    然而,这种调度也可以用来做其他的事情,比如 keep-alive 和 Suspense。甚至像并发渲染这样的功能也可以用这种方式来实现,从而充分体现了如何同时利用基于推送和拉取的方式能够达成的最佳效果。

     

    编译

     

    在 2019 年,Svelte 3向我们展示了利用编译器能够完成多少事情。实际上,他们将反应性完全编译掉了。在这过程中,也会有一些权衡,Svelte 向我们展示了编译器如何抹平人类工程学方面的欠缺。这将会成为一种趋势。

     

    反应式语言(如状态、衍生状态、作用)不仅向我们描述了用户界面等同步系统所需的所有内容,而且它是可分析的。我们可以精确地知道都发生了哪些变更以及它们发生在什么地方。可追溯性的潜力是很深远的。

     

    来自Preact团队的 Marvin Hagemeister在Twitter这样说到,“我认为这是基于 Signals 的方式优于钩子(hook)的主要原因之一。它能够使我们添加更多的调试洞察力,这是钩子所无法实现的,比如准确地显示一个状态发生变更的原因。”

     

    如果能够在编译时知道这一切,我们就可以交付更少的 JavaScript 代码。对于代码的加载,我们会有更高的自由度。这就是QwikMarko的可恢复性的基础。

     

    面向未来的 Signals

     

    Angular 团队的成员 Pawel Kozlowski 则认为

     

    “Signals 是新的 VDOM。

     

    人们对它的兴趣正在爆发:很多人正在尝试一些新东西。这将使我们能够探索该领域,尝试不同的策略,对其增进了解和优化。

     

    虽然现在不知道最终结果是什么,但是这种集体探索是很好的!”

     

    鉴于这项技术已经非常古老,说还有很多东西需要探索,这可能会令人感到惊讶。但是,这里的原因在于,它是一种对解决方案进行建模的方式,而不是一种具体的方案。它所提供的是一种描述状态同步的语言,与要让它执行的副作用完全无关。

     

    因此,它能够被 Vue、Solid、Preact、Qwik 和 Angular 采用似乎并不足为奇。我们已经看到它进入了 Rust 的 Leptos 和 Sycamore,表明 DOM 上的 WASM不一定会慢。React 甚至考虑在底层使用它。

     

    来自 React 核心团队的 Andrew Clark表示

     

    “我们可能会在 React 中添加一个类似 Signals 的基元,但我并不认为这是一个编写 UI 代码的好方法。它对性能来说是很好的。但我更喜欢 React 的模式,在这种模式下,你每次都会假装重新创建所有的内容。我们的计划是使用一个编译器来实现与之相当的性能”。

     

    也许这是一种合适的方式,因为 React 的虚拟 DOM 始终只是一个实现细节。

     

    Signals 和反应性语言似乎是一个交汇点。但是,这在 JavaScript 诞生之初却并不那么明显。也许这是因为 JavaScript 并不是最好的语言。我甚至可以说,长期以来,我们在前端框架设计中感受到的很多痛苦都是语言本身的问题。

     

    无论这一切的结局如何,到目前为止,都是一次相当不错的旅程。有这么多人关注 Signals,我迫不及待地想知道我们的下一步会是什么。

     

    原文链接:

    https://dev.to/this-is-learning/the-evolution-of-signals-in-javascript-8ob

    相关阅读:

    手写一个 react,看透 react 运行机制

    看透 react 源码之感受 react 的进化

    2023 重学 Angular

    初识 VUE 响应式原理

    2023-04-10 12:445232

    评论

    发布
    暂无评论
    发现更多内容

    堡垒机审计日志的定义以及作用概述

    行云管家

    数字化 堡垒机 IT信息

    即时通讯技术文集(第39期):推送技术合集(Part1) [共18篇]

    JackJiang

    即时通讯;IM;网络编程

    实时数据驱动电站管理,EMQX 助力黑马高科光伏电站运维监控

    EMQ映云科技

    mqtt 光伏发电 emqx 新能源行业 mqtt broker

    Master-Worker 架构的灰度发布难题

    阿里技术

    架构 分布式 master Master-Worker Master-Worker 架构

    容器网络实现(中):为容器插上”网线“

    EquatorCoco

    php 容器 网络

    数据库市场或迎变局 天翼云TeleDB打造企业数据管理最优解

    Geek_2d6073

    Mock 工具使用 - 模拟弱网测试

    霍格沃兹测试开发学社

    接口测试 Mock 工具使用 - 弱网测试

    测吧(北京)科技有限公司

    测试

    如何清理mac磁盘?快速清理小妙招在这里

    阿拉灯神丁

    软件 Mac 软件 电脑 CleanMyMac X

    优化mac储存空间的方法 解决苹果电脑不流畅卡顿

    阿拉灯神丁

    Mac 软件 存储空间 CleanMyMac X 激活码生成器 苹果软件

    Cockos Reaper for Mac(专业数字音频制作软件)v7.16激活版

    iMac小白

    新规:互联网政务应用安全管理规定将于7月1日正式执行

    行云管家

    互联网 政务

    碳实践|如何快速掌握组织碳核算中范围3的计算方法

    AMT企源

    数字化转型 双碳 碳管理 碳核算

    开源鸿蒙的到来,鸿蒙生态该如何走向?

    Geek_2305a8

    心诺安 x TapData:快速搭建云中数仓,助力电商企业实施“以用户为中心的”精细化运营

    tapdata

    数据库

    Flink⼤状态作业调优实践指南:Flink SQL 作业篇

    Apache Flink

    大数据 flink flink sql

    抖音面试:说说延迟任务的调度算法?

    王磊

    OpenAI 发布的 GPT-4o是什么,有什么功能?

    蓉蓉

    openai gpt4o

    【AI应用开发全流程】使用AscendCL开发板完成模型推理

    华为云开发者联盟

    华为云 开发板 昇腾 华为云开发者联盟 企业号2024年6月PK榜

    揭秘业务系统数据安全三大核心问题:“谁在用”、“用什么”和“怎么用”

    极盾科技

    数据安全

    备受Vue、Angular和React青睐的Signals演进史_大前端_Ryan Carniato_InfoQ精选文章