一. solid
介绍
solid
是前端框架,开发体验与React
类似,使用jsx
语法。本文主要解析solid
与react
的渲染流程差异和solid
的signals
机制。
solid
使用示例
// App.jsx
import { createSignal } from 'solid-js'
function App() {
const [counter, setCounter] = createSignal(0)
return (
<div>
<h1 onClick={() => setCounter(s => s + 1)}>{counter()}</h1>
</div>
)
}
export default App
// main.js
import { render } from 'solid-js/web'
import App from './App'
const root = document.getElementById('root')
render(() => <App />, root)
二. solid
原理
solid
编译原理部分本文不做介绍,这里需要知道的是solid
首先会编译组件方法,在编译转换的过程中有一些优化机制,核心是优化运行时的性能。
例如下面这段代码,编译转换后的结果如下
// 转换前
import { createSignal } from 'solid-js'
function Counter() {
const [counter, setCounter] = createSignal(0)
return (
<div>
<h1 onClick={() => setCounter(s => s + 1)}>{counter()}</h1>
</div>
)
}
export default Counter
// 转换后
const _REGISTRY = _$$registry();
var _tmpl$ = _$template(`<div><h1>`);
var Counter = _$$component(_REGISTRY, "Counter", function Counter2() {
const [counter,setCounter] = createSignal(0);
return ( () => {
var _el$ = _tmpl$()
, _el$2 = _el$.firstChild;
_el$2.$$click = () => setCounter( (s) => s + 1);
_$insert(_el$2, counter);
return _el$;
}
)();
});
export default Counter;
_$delegateEvents(["click"]);
2.1 渲染流程
solid
渲染流程中使用了虚拟DOM
树,相比React
,solid
的虚拟DOM
树更加精炼,对于一些静态的节点并不会创建其对应的虚拟DOM
节点,只会创建动态节点对应的虚拟DOM
节点。
例如下面这段代码,在React
渲染流程中,div
和两个h1
标签都会创建对应的Fiber
节点,但是在solid
中,只会创建第二个h1
标签的文本节点对应的虚拟DOM
节点,所以solid
构建的虚拟DOM
树占用的内存开销和运行性能都比React
要好得多。
<div>
<h1>hello world</h1>
<h1>{count}<h1>
</div>
在首次渲染中,会采用深度优先遍历算法递归创建虚拟DOM
节点,且同时创建其对应的真实DOM
节点,然后会将真实DOM
节点插入到父DOM
节点中,当整个虚拟DOM
树构建完成后,会将创建好的真实DOM
树插入到页面指定节点上完成首次渲染流程。
当状态更新时,会触发更新渲染,与React
不同的是,solid
不会重新创建新的虚拟DOM
树,而是找到需要更新的虚拟DOM
节点,然后执行更新逻辑。需要注意的是solid
更新时机默认是同步的。
2.2 signal
solid
的signal
对象数据结构如下,核心关注以下属性:
value
属性记录当前状态,例如state
的初始值observers
属性记录依赖该signal
的虚拟DOM
节点,当signal
状态变更时会触发observers
属性记录的虚拟DOM
节点更新渲染comparator
属性用于判断signal
状态是否变更
const s = {
value,
observers: null,
observerSlots: null,
comparator: options.equals || undefined
};
signal
机制本质是对订阅/发布设计模式的应用,当调用createSignal
方法时会创建signal
对象,对应发布者角色,而虚拟DOM
节点对应订阅者角色,当访问signal
对象属性时会被记录到observers
属性中,当signal
状态值更新时,会触发虚拟DOM
节点更新渲染。
三. 总结
solid
在编译阶段有一些优化机制,优化运行时的性能。在渲染流程中构建的虚拟DOM
树相比React
也更加精炼,当触发更新渲染时,只需要找到需要更新的虚拟DOM
节点,执行其对应的更新逻辑即可。solid
是一个很优秀的框架,在内存开销和运行性能上都做到了极致。