SolidJS硬气的说:我比React还react

  发布时间:2025-11-05 15:49:19   作者:玩站小弟   我要评论
大家好,我是卡颂。最近刷推时,有个老哥经常出现在「前端框架」相关推文下。一副憨厚的样貌我想:“老哥你哪位?”一查,原来是个框架作者,作品叫SolidJS[1]。翻翻框架介绍,这句话成功吸引我的注意:支 。

大家好,说比我是说比卡颂。

最近刷推时,说比有个老哥经常出现在「前端框架」相关推文下。说比

一副憨厚的说比样貌 

我想:“老哥你哪位?”

一查,原来是说比个框架作者,作品叫SolidJS[1]。说比

翻翻框架介绍,说比这句话成功吸引我的说比注意:

支持现代前端特性,例如:JSX,说比 Fragments, Context, Portals, Suspense, Streaming SSR, Progressive Hydration, Error Boundaries和Concurrent Rendering

我琢磨您不会是React在逃公主吧?这不能说和React类似,只能说完全一样吧?说比

作为传统中国人,秉承「来都来了」思想,说比我试用了一天,说比又看了下源码,说比结果发现这个框架真是说比个宝藏框架。

本文会比较SolidJS与React的异同,阐述他的独特优势,看完后不知道你会不会和我发出同样的感叹:

这简直比React还react(react译为响应)

相信看完本文后,不仅能认识一个新框架,还能对React有更深的认识。

开整!

初看很相似

让我们从一个「计数器」的例子看看与React语法的差异:

import { render } from "solid-js/web"; import { createSignal } from "solid-js"; function Counter() {   const [count, setCount] = createSignal(0);   const increment = () => setCount(count() + 1);   return (     <button type="button" onClick={increment}>            </button>   ); } render(() => <Counter />, document.getElementById("app")); 

和React不同的地方:

useState改名成createSignal 获取count状态从React中直接使用count变为通过方法调用,免费信息发布网即:count()

难道仅仅是一个类React框架?

别急,让我们从「编译时」、「运行时」、「响应原理」三方面来看看。

编译时大不同

React的编译时很「薄」,基本只是编译JSX语法。

而SolidJS则采用了类似Svelte的方案:在编译时,将状态更新编译为独立的DOM操作方法。

这样做有什么好处?主要有两点。

一定条件下的体积优势

你不需要为你没使用的代码付出代价

使用React时,即使没有用到Hooks,其代码也会出现在最终编译后的代码中。

而在SolidJS中,未使用的功能不会出现在编译后的代码中。

举个例子,上面计时器的例子中,编译后的代码有一行是这样:

delegateEvents(["click"]); 

这行代码的目的是在document上注册click事件代理。亿华云

如果在计时器中没有使用onClick,那么编译后代码中就不会有这一行。

有热心网友对比了类似编译时方案的Svelte与React之间「源代码」与「编译后代码」的体积差异。

其中横轴代表源代码体积,纵轴代表编译后代码体积,红色线条代表Svelte,蓝色代表React:

可见,在临界值(业务源代码体积达到120kb)之前,编译时方案有一定体积优势。

由于SolidJS使用JSX描述视图,比Svelte使用类似Vue的模版语法更灵活,所以在编译时没法做到Svelte一样的极致编译优化,使得其相比Svelte运行时更重一点。

这为他带来了额外的好处:在真实项目(>120kb)中,SolidJS的代码体积比Svelte小25%左右。

还真是,因祸得福?

更快的更新速度

我们知道,在React与Vue中存在一层「虚拟DOM」(React中叫Fiber树)。

每当发生更新,「虚拟DOM」会进行比较(Diff算法),比较的结果会执行不同的DOM操作(增、删、改)。免费源码下载

而SolidJS与Svelte在发生更新时,可以直接调用编译好的DOM操作方法,省去了「虚拟DOM比较」这一步所消耗的时间。

举个例子,上文的计时器,当点击后,从触发更新到视图变化的调用栈如下:

触发事件,更新状态,更新视图,一路调用走到底,清晰明了。

同样的例子放到React中,调用栈如下:

左中右红、绿、蓝框调用栈分别对应:

处理事件 对比并生成Fiber树 根据对比结果执行DOM操作

可见,SolidJS的更新路径比React短很多。

你问凭什么?这还得从其特殊的「响应原理」聊起。

响应原理

假设有个状态name,初始值为KaSong。我们希望根据name渲染一个div。

SolidJS编译后的代码类似:

const [name, setName] = createSignal("KaSong"); const el = document.createElement("div"); createEffect(() => el.textContent = name()); 

其中createEffect类似React的useEffect。

由于其回调内依赖了name,所以当name改变后会触发createEffect回调,改变el.textContent,造成DOM更新。

类似React的:

useEffect(() => {   el.textContent = name; }, [name]) 

首屏渲染结果:

<div>KaSong</div> 

 接下来,触发更新:

setName("XiaoMing")  

更新后结果:

<div>XiaoMing</div> 

 为什么更新name后会触发createEffect?

这里也没有什么黑魔法,就是「订阅发布」。

createEffect回调依赖name,所以会订阅name的变化。

由于篇幅有限,实现细节咱下回细聊。

这里的关键在于,SolidJS的状态具有「原子性」。

即状态互相之间有依赖关系,他们形成局部的依赖图。当改变一个状态后,依赖图中的其他状态也会改变。

createEffect中如果使用了这些依赖,就会订阅他们的变化。

当状态改变后,createEffect回调会执行,进而执行具体的DOM方法,更新视图。

「真」。「响应式更新」,指哪打哪,李云龙直呼内行。

有同学会问,React不是这样么?

那我问你个问题:

为什么Hooks会有调用顺序不能变的要求?

为什么useEffect回调会有闭包问题?

答案已经呼之欲出了:React只有在这些限制下才能实现「响应式」。

辛劳苦干React

有一个可能反直觉的知识:React并不关心哪个组件触发了更新。

在React中,任何一个组件触发更新(如调用this.setState),所有组件都会重新走一遍流程。因为需要构建一棵新的Fiber树。

为了减少无意义的render,React内部有些优化策略用来判断组件是否可以复用上次更新的Fiber节点(从而跳过render)。

同时,也提供了很多API(比如:useMemo、PureComponent...),让开发者告诉他哪些组件可以跳过render。

如果说,SolidJS的更新流程像一个画家,画面中哪儿需要更新就往哪儿画几笔。

那么React的更新流程像是一个人拿相机拍一张照片,再拿这张照片和上次拍的照片找不同,最后把不同的地方更新了。

总结

今天,我们聊了SolidJS与React的差异,主要体现在三方面:

编译时 运行时 响应原理

不知道你喜欢这款:没有Hooks顺序限制、没有useEffect闭包问题、没有Fiber树、比React更react的框架么?

如果你问我选哪个?当然,哪个给工资高我用哪个。

考资料

[1]SolidJS:

https://github.com/solidjs/solid

  • Tag:

相关文章

  • 富勒G60(豪华、高性能、环保,一辆领先的电动SUV)

    摘要:在当前对环境保护和可持续发展的呼声日益高涨的背景下,电动汽车成为了人们关注的焦点。富勒G60作为一款突破性的电动SUV,不仅拥有豪华的内饰和高性能的动力系统,更以其出色的续航里程和...
    2025-11-05
  • 26年历史一刻!中国500强数量首超美国

    2020年《财富》世界500强排行榜正式发布。今年《财富》世界500强排行榜企业的营业收入达到33万亿美元,创下历史新高,接近中美两国GDP的总和。进入排行榜的门槛最低销售收入)也从248亿美元提高到
    2025-11-05
  • 突然登上GitHub热榜!谷歌的这款测试工具,别告诉我你不知道

    在一些项目中,有些测试问题,是无法通过集成测试解决的,比较合适的方法是通过单元测试。谷歌有一个名为Google test的C++测试框架,它能够帮助我们比较方便的进行测试代码的编写,以及输出尽可能详细
    2025-11-05
  • 100%让你在10分钟内学会如何用Python将数据批量的插入到数据库

    我是一名挣扎在编程链底端的pythoner,工作中既要和数据打交道,也要保持和erp系统,web网站友好的"沟通"···,我会时不时的分享下工作中遇到那点事,包括个人觉得值得记录的编程小技巧,还有就是
    2025-11-05
  • 神舟战神Z6(探索神舟战神Z6的惊艳性能和令人陶醉的游戏体验)

    摘要:自从神舟战神Z6问世以来,其卓越的性能和引人入胜的游戏体验就一直是人们津津乐道的话题。无论是游戏玩家、专业用户还是普通消费者,都对这款电脑有着极高的期待。本文将从各个方面深入探讨神...
    2025-11-05
  • 快来测试Python开发工具pipenv的新版本

    pipenv是一个可帮助 Python 开发人员维护具有特定一组依赖关系的隔离虚拟环境,以实现可重新复制的开发和部署环境的工具。它类似于其他编程语言中的工具如 bundler、composer、npm
    2025-11-05

最新评论