SolidJS硬气的说:我比React还react
SegmentFault
共 3775字,需浏览 8分钟
·
2021-09-14 23:31
大家好,我是卡颂。
最近刷推时,有个老哥经常出现在前端框架相关推文下。
我想:“老哥你哪位?”
一查,原来是个框架作者,作品叫SolidJS。
翻翻框架介绍,这句话成功吸引我的注意:
支持现代前端特性,例如: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}>
{count()}
</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
:SolidJS
使用JSX
描述视图,比Svelte
使用类似Vue
的模版语法更灵活,所以在编译时没法做到Svelte
一样的极致编译优化,使得其相比Svelte
运行时更重一点。SolidJS
的代码体积比Svelte
小25%左右。更快的更新速度
React
与Vue
中存在一层虚拟DOM(React
中叫Fiber
树)。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
的框架么?评论