Solid-js
用于构建用户界面的声明式、高效且灵活的 JavaScript 库
您可以在 官方教程 中尝试下面提到的部分例子,本文引用并简化了官方教程中的部分例子
本文讲述部分 solid 主要内容,更多详细内容,移步 Solid API 文档
Solid 使用了和 React 相似的语法和类似 Svelte 的预编译
Solid 使用上类似于 React,使用 JSX 语法,但不同于 React, 组件只会初始化一次,并不是 state 改变就重新运行渲染整个组件,这类似于 Vue3 的 setup
为什么选择 Solid
Solid 官网 给出了以下理由
- 高性能 - 始终在公认的 UI 速度和内存利用率基准测试中名列前茅
- 强大 - 可组合的反应式原语与 JSX 的灵活性相结合
- 务实 - 合理且量身定制的 API 使开发变得有趣而简单
- 生产力 - 人体工程学和熟悉程度使构建简单或复杂的东西变得轻而易举
主要优势
高性能 - 接近原生的性能,在 js-framework-benchmark 排名中名列前茅
极小的打包体积 - 编译为直接的DOM操作,无虚拟DOM,极小的运行时(类似于 Svelte),适合打为独立的 webComponent 在其它应用中嵌入
易于使用 - 近似 React 的使用体验,便于快速上手
快速开始
新建项目
npx degit solidjs/templates/js my-app
cd my-app
npm i
npm run dev
基本示例
这里将 App 组件渲染到 body 容器中
这里修改默认示例, 从零开始尝试
// App.JSX
import {
render } from "solid-js/web";
function App() {
return (
<div>Solid My App</div>
);
}
// 组件声明也可以直接用箭头函数
/*
const App = ()=> (<div>Solid My App</div>);
*/
render(() => <App />, document.querySelector("body"));
是不是看起来非常熟悉,就和 React 一样,非常舒服
导入组件,传递组件,props
与 React 类似的使用方法, 但不能解构 props,否则将失去反应性
// App.JSX
import {
render } from "solid-js/web";
import Component1 from "./Component1.jsx";
function App() {
return (
<div>
Solid My App
<Component1 text={
"component1"}>
<div>children</div>
</Component1>
</div>
);
}
render(() => <App />, document.querySelector("body"));
// Component1.jsx
export default function Component1(props) {
return (
<div>
{
props.text}
{
props.children}
</div>
)
}
反应性
createSignal
signal 是 Solid 中最基本的反应性单元,此函数类似于 React 的 useState,但返回函数用于获取调用它获取值,而不是像 React 一样直接取得值,下列是一个基本的 Counter 示例
import {
createSignal } from "solid-js";
export default function Counter() {
const [count, setCount] = createSignal(0);
return (
<button onClick={
()=> setCount(count() + 1)}>
{
count()}
</button>
)
}
createMemo
createMemo 用于生成只读的派生值,类似于 Vue 中的 computed,与上面的相同,也需要通过调用来获取值
import {
createSignal, createMemo } from "solid-js";
export default function Counter() {
const [count, setCount] = createSignal(0);
// count 的平方派生自 count,在依赖改变的时候自动更新
const countPow2 = createMemo(()=> count() ** 2);
return (
<button onClick={
()=> setCount(count() + 1)}>
{
count()} | {
countPow2()}
</button>
)
}
createEffect
createEffect 一般用于副作用,在状态改变的时候运行副作用
它类似于 React 中的 useEffect 但其自动收集依赖,无需显式声明依赖,这和 Vue 中的 watchEffect 作用相同
import {
createSignal, createEffect } from "solid-js";
export default function Counter() {
const [count, setCount] = createSignal(0);
// 每当依赖改变就会重新运行该副作用
createEffect(()=> console.log(count()));
return (
<button onClick={
()=> setCount(count() + 1)}>
{
count()}
</button>
)
}
如果需要显式声明依赖,参考 Solid createEffect 显式声明依赖
batch
Solid 的反应性是同步的,这意味着在任何更改后的下一行 DOM 都会更新。在大多数情况下,这完全没问题,因为 Solid 的粒度渲染只是反应式系统中更新的传播。“渲染”两次无关的更改实际上并不意味着浪费工作。
如果更改是相关的怎么办?Solid 的batch助手允许将多个更改排队,然后在通知观察者之前同时应用它们。在批处理中更新的信号值直到完成才会提交。
参考以下不使用 batch 的例子
import {
render } from "solid-js/web";
import {
createSignal, batch } from "solid-js";
const App = () => {
const [firstName, setFirstName] = createSignal("John");
const [lastName, setLastName] = createSignal("Smith");
const