2023 年了,我即将跑路的同事出去面试的时候,告诉我发现面试官还在问“不同框架的响应式有什么区别”这样老生常谈的问题!
正好最近看到 Qwik 的作者 Miško Hevery 分享了自己的一些见解,非常简洁清晰,学完了可以直接对付面试官了。
以下是我整理的原文:
我想分享一下我对当前响应式方法和格局的理解。以下是我个人的观点和意见,其中一些可能有些激进,所以做好准备。(我并不是说我的观点是正确的,但这就是我对这个世界的看法。)
我认为通过分享自己的观点,我们可以在行业中达成共识,我希望这些我多年来辛苦获得的见解对他人有所帮助,可以补充他们对问题的理解中的缺失部分。此外,我非常重视反馈,毕竟即使经过这么多年,我的理解也更像是一个精心编织的网络,而不是坚固的钢笼。
响应式的三位一体
我认为迄今为止,在行业中有三种基本的响应式方法:
- 基于值(Value-based);即脏检查(Angular、React、Svelte)
- 基于 Observable:(Angular 使用 RxJS、Svelte)
- 基于 Signal:(Signals 加持的 Angular、Qwik、MobX 加持的 React、Solid、Vue)
基于值(Value-based)
基于值的系统依赖于将状态存储在本地(非可观察)引用中,作为简单的值。
当我说“可观察”时,我并不是指像 RxJS 这样的 Observables。我指的是可观察这个词的常见用法,即知道何时发生变化。而“非可观察”意味着没有办法知道值在具体的时间点上发生了变化。
React
代码语言:javascript复制function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count 1)}>{count}</button>;
}
Angular
代码语言:javascript复制import { Component } from "@angular/core";
@Component({
selector: "app-counter",
template: `
<h1>Counter: {{ count }}</h1>
<button (click)="increment()">Increment</button>
`,
})
export class CounterComponent {
count: number = 0;
increment() {
this.count ;
}
}
Svelte
代码语言:javascript复制<script>
let count = 0;
function increment() {
count = 1;
}
</script>
<div>
<h1>Counter: {count}</h1>
<button on:click={increment}>Increment</button>
</div>
在上述每种情况下,状态以值的形式存储,可以是变量、封闭在变量中,或者是属性。但关键是它只是一个非可观察的值,以一种不允许框架在值发生变化时知道(观察)的方式存储在 JavaScript 中。
由于值是以一种不允许框架观察到的方式存储的,每个框架都需要一种方式来检测这些值的变化并将组件标记为"dirty"。
一旦标记为"dirty",组件会重新运行,以便框架可以重新读取/重新创建这些值,从而检测哪些部分发生了变化,并将变化反映到 DOM 中。