前言
Solid.js,一个比 React 更 react 的框架。每一个使用 React 的同学,你可以不使用,但不应该不了解。
目前 Solid.js 发布了最新的官方文档,但却缺少对应的中文文档。为了帮助大家学习 Solid.js,故有此系列。
我同时搭建了 Solid.js 最新的中文文档站点:solid.yayujs.com ,欢迎勘误。
虽说是翻译,但个人并不喜欢严格遵守原文,为了保证中文阅读流畅,会删减部分语句,对难懂的部分也会另做补充解释,希望能给大家带来一个好的中文学习体验。
欢迎围观朋友圈、加入低调务实优秀中国好青年前端社群,感受不一样的前端社群。
响应式介绍
注意:虽然本指南对于理解响应式系统很有帮助,但它会用到一些 Solid 中才有的术语。
响应式(Reactivity)增强了 Solid 应用程序的交互性。这种编程范式是指系统自动响应数据或状态变化的能力。对于 Solid,响应式是其设计基础,确保应用程序与底层数据保持最新。
响应式的重要性
- 响应式使用户界面 (UI) 和状态保持同步,从而减少手动更新的需要。
- 实时更新创造了更具响应性和交互性的用户体验。
javascript
function Counter() {
const [count, setCount] = createSignal(0);
const increment = () => setCount((prev) => prev + 1);
return (
<div>
<span>Count: {count()}</span>{" "}
{/* 当按钮点击的时候,只有 `count()` 会被更新 */}
<button type="button" onClick={increment}>
Increment
</button>
</div>
);
}
在这段代码中,Counter
函数设置了一个按钮,当点击该按钮时,调用 increment
函数将 count
加 1。更新时,只会更新展示的数字,而不会重新渲染整个组件。
响应式原理
信号(Signals)
信号是响应式系统的核心元素,在数据管理和系统响应中发挥着重要作用。信号负责存储和管理数据,以及触发整个系统的更新。这背后是通过使用 getter 和 setter 来完成的。
scss
const [count, setCount] = createSignal(0);
// ^ getter ^ setter
- Getter:负责访问信号当前值的函数。您可以调用 getter 来访问存储在信号中的数据
- Setter:负责修改信号值的函数。调用 setter 更新信号的值,同时会触发应用程序的响应式更新。
perl
console.log(count()); // `count()` 是一个 getter,返回 `count` 的当前值即 `0`.
setCount(1); // `setCount` 是一个 setter, 更新 `count` 的值.
console.log(count()); // 更新后的 `count` 值是 `1`.
订阅者(Subscribers)
订阅者是响应式系统的另一个核心元素。他们负责跟踪信号的变化并相应地更新系统。它们是自动响应程序,保持系统与最新的数据变化同步。
订阅者的工作原理基于两个主要动作:
- 观察(Observation) : 本质上,订阅者观察信号,这使得订阅者随时准备好捕捉它们正在追踪的信号的任何变化。
- 响应(Response) : 当信号发生变化时,订阅者会收到通知。这会触发订阅者对信号的变化做出响应。这可能包括更新 UI 或调用外部函数等任务。
scss
function Counter() {
const [count, setCount] = createSignal(0);
const increment = () => setCount((prev) => prev + 1);
createEffect(() => {
console.log(count());
});
// 每次 `count` 值改变,`createEffect` 都会触发 console log.
}
状态管理
状态管理是指管理应用程序状态的过程。这涉及存储和更新数据,以及响应数据的变化。
在 Solid 中,状态管理通过信号和订阅者实现。信号用于存储和更新数据,而订阅者用于响应数据变化。
追踪变化
追踪变化涉及监控数据的任何更新并相应地做出响应。这是通过使用订阅者来完成的。
当信号在追踪作用域内未被访问时,对信号的更新将不会触发更新。这是因为如果信号没有被追踪,它无法通知任何订阅者发生了变化。
scss
const [count, setCount] = createSignal(0);
console.log("Count:", count());
setCount(1);
// 输出: Count: 0
// `count` 没有被追踪, 所以当 `count` 改变的时候,console log 不会更新.
由于初始化是一次性事件,虽然访问了信号,但在追踪作用域之外,所以不会追踪该信号。要想追踪信号,需要在订阅者的作用域内访问该信号。响应式原语(Reactive primitives),例如 effects,可用于创建订阅者。
scss
const [count, setCount] = createSignal(0);
createEffect(() => {
console.log("Count:", count());
});
setCount(1);
// 输出: Count: 0
// Count: 1
更新 UI
Solid 应用程序的 UI 使用 JSX 构建。JSX 在幕后创建了一个追踪作用域,这使得可以在组件的返回语句中追踪信号。
javascript
function Counter() {
const [count, setCount] = createSignal(0);
const increment = () => setCount((prev) => prev + 1);
return (
<div>
<span>Count: {count()}</span>{" "}
{/* ✅ 当 `count()` 改变时会更新. */}
<button type="button" onClick={increment}>
Increment
</button>
</div>
);
}
组件与其他函数非常相似,只会运行一次。这意味着如果在 return 语句之外访问信号,它将在初始化时运行,但对该信号的任何更新都不会触发更新。
javascript
function Counter() {
const [count, setCount] = createSignal(0);
const increment = () => setCount((prev) => prev + 1);
console.log("Count:", count()); // ❌ 不会被追踪 - 只会在初始化的时候运行一次.
createEffect(() => {
console.log(count()); // ✅ 只要 `count()` 改变,就会更新.
});
return (
<div>
<span>Count: {count()}</span>{/* ✅ 只要 `count()` 改变,就会更新. */}
<button type="button" onClick={increment}>
Increment
</button>
</div>
);
}
了解更多在 Solid 中管理状态的内容,请访问状态管理指南。
同步 vs. 异步
响应式系统旨在对数据的变化做出响应。这些响应可以是即时的,也可以是延迟的,具体取决于系统的性质。通常,这两者之间的选择取决于应用程序的要求和所涉及任务的性质。
同步响应
同步响应是 Solid 的默认响应模式,在这种模式下,系统以直接和线性的方式响应变化。当信号发生变化时,对应的订阅者会立即有序更新。
通过同步响应,系统能够以可预测的方式响应变化。这在讲究更新顺序的场景中非常有用。例如,如果一个订阅者依赖于另一个信号,那么就需要确保在其依赖的信号之后更新订阅者。
scss
const [count, setCount] = createSignal(0);
const [double, setDouble] = createSignal(0);
createEffect(() => {
setDouble(count() * 2);
});
在这个例子中,因为同步响应,double
将始终在 count
之后更新。这可确保 double
始终与 count
的最新值保持同步。
异步响应
异步响应是指系统以延迟或非线性的方式响应变化。当信号发生变化时,相应的订阅者不会立即更新。相反,系统会等待特定事件或任务完成后再更新订阅者。
这在订阅者依赖多个信号的场景中非常重要。在这些场景下,在另一个信号之前更新一个信号可能会导致数据不一致。所以如果订阅者依赖于两个信号,系统需要在更新订阅者之前等待两个信号都更新。
注意:当存在异步响应时,确保系统能够在更新时处理延迟非常重要。 batch 可用于延迟更新,以便订阅者在每个信号都更新后运行。
关键概念
- 信号是响应式系统的核心元素。它们负责存储和管理数据
- 信号基于 getter 和 setter,所以信号既可读又可写。
- 订阅者是自动响应,可以追踪信号的变化并相应地更新系统。
- 信号和订阅者一起确保了系统能够与最新的数据变化保持一致。
- 响应式系统建立在数据驱动响应式的原则之上。这意味着系统的响应式是由其构建的数据驱动的。
- 响应式系统可以是同步的,也可以是异步的。
如果您想更深入地了解,请访问有关细粒度响应式指南。