Files
test-repo/docs/zh-cn/appendix/3-browser-and-frontend/frontend-framework-nature.md
T
sanbuphy 6098908eee feat(docs): add interactive demos and complete content for development tools
- Add Vue components for interactive demos (SSH auth, regex, env vars, ports)
- Complete markdown content for SSH, regex, environment variables, and ports
- Remove placeholder "待实现" sections and replace with detailed guides
- Add visual explanations for key concepts like ports and localhost
- Include practical examples and troubleshooting tips
- Add component for showing evolution from transistors to CPU
- Improve documentation structure and navigation
- Add security best practices for API keys and environment variables
2026-02-21 10:04:47 +08:00

474 lines
25 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 前端框架的本质
> 💡 **学习指南**:这篇文章会回答一个根本问题——**前端框架(Vue、React、Svelte 等)到底在做什么?** 如果你只学过 HTML、CSS 和一点 JavaScript,完全没问题,我们从头讲起。
在开始之前,先确认你知道这两个基础概念。如果不确定,可以先看对应章节:
- **HTML**:网页的骨架,定义页面上有哪些元素(标题、段落、按钮、图片……)。参见 [HTML 与 CSS 布局](./html-css-layout.md)。
- **JavaScript**:让网页"动起来"的编程语言,可以修改页面内容、响应用户操作。参见 [JavaScript 深度指南](./javascript-deep-dive.md)。
还有一个概念会在后面频繁出现,这里先做一个完整的说明。
### 什么是 DOM
DOM 的全称是 Document Object Model,中文叫"文档对象模型"。
当你在浏览器中打开一个网页时,浏览器做的第一件事就是读取 HTML 代码。读完之后,浏览器不会直接拿 HTML 文本去显示页面,而是先把 HTML 代码**转换成一棵树形结构**,存放在内存里。这棵树就叫 DOM 树。
树上的每一个节点(Node)对应 HTML 里的一个标签。标签之间的嵌套关系,在 DOM 树里就变成了父节点和子节点的关系。
👇 **动手试试看**
把鼠标移到左边的 HTML 代码上,右边 DOM 树中对应的节点会高亮。反过来也一样。每一行 HTML 标签都对应 DOM 树上的一个节点。
<WhatIsDomDemo />
**为什么要了解 DOM** 因为 JavaScript 修改页面的方式,就是操作这棵 DOM 树——增加节点、删除节点、修改节点的内容。而前端框架做的核心工作,就是帮你自动化这些 DOM 操作。后面我们会反复提到 DOM,理解它是理解框架原理的基础。
---
## 0. 引言:什么是"前端框架"?
先解释"框架"这个词。在编程中,**框架(Framework)** 是一套已经写好的代码和规则,它规定了你的代码应该怎么组织、怎么运行。你按照它的方式写代码,它帮你处理大量重复、繁琐的底层工作。
**前端框架**,就是专门帮你**构建网页界面**的框架。目前最常见的有 Vue、React、Svelte、Angular 这几个。
那它们到底帮你解决了什么问题?下面这三张卡片概括了核心逻辑:
<FrameworkMotivationDemo />
接下来我们一步步展开,从最基础的问题讲起。
---
## 1. 核心问题:数据变了,界面怎么办?
### 1.1 先搞清楚"数据"和"界面"是什么
在任何一个网页应用中,都有两个东西在同时存在:
- **数据(Data / State**:程序内部存储的信息。比如"购物车里有 3 件商品"、"用户名是张三"、"当前选中了第 2 个标签页"。这些数据存在 JavaScript 的变量里,用户看不到它们。
- **界面(UI)**:用户在屏幕上看到的东西。比如页面上显示"购物车(3)"、显示"欢迎,张三"、第 2 个标签页高亮。这些是 HTML 元素呈现出来的视觉效果。
**数据和界面之间有对应关系**:数据是"3 件商品",界面上就应该显示"3"。如果数据变成了"4 件商品",界面上也应该跟着变成"4"。
问题是:**这个"跟着变"的过程,谁来负责?**
👇 **动手点点看**
点击"添加商品"按钮,注意观察:数据(左边)已经变了,但界面(右边)没有跟着更新——它们之间"断开"了。再点"同步界面"手动修复。
<DataUIGapDemo />
### 1.2 为什么 JavaScript 变量变了,界面不会自动变?
这是零基础最容易困惑的地方,我们把底层原理一步步讲清楚。
在 JavaScript 中,变量就是一块内存空间,用来存放数据。当你执行 `count = count + 1` 时,JavaScript 引擎做的事情非常简单:把内存中 count 这个位置的值从 3 改成 4。**做完这一步就结束了,不会再发生任何事。**
而页面上显示的内容(比如 `<span>3</span>` 这个 DOM 节点)存放在另一块完全不同的内存空间里。JavaScript 引擎在修改变量时,根本不知道页面上有一个 DOM 节点正在显示这个变量的值,也没有任何机制让它去检查。
所以本质原因是:**JavaScript 的变量和 DOM 节点是两块独立的内存,它们之间没有任何自动联动机制。** 修改变量只改变了变量所在的内存,DOM 节点所在的内存不会受到任何影响。
```javascript
let count = 3
// 页面上有一个 DOM 节点显示着 count 的值:
// <span id="counter">3</span>
count = 4
// JavaScript 引擎做了什么?
// → 把变量 count 在内存中的值从 3 改成 4
// → 结束。没了。
// 页面上 <span> 里显示的仍然是 "3"
```
如果你想让页面上的显示也变成"4",你必须**额外写代码**,手动找到那个 DOM 节点,然后修改它的内容:
```javascript
count = 4 // 第 1 步:改变量
// 第 2 步:你必须自己写——找到 DOM 节点,把它的文字改成新值
document.getElementById('counter').textContent = count
```
如果页面上有 5 个地方显示着 count 的值(购物车数量、商品列表、总价、小计、状态提示),你就需要写 5 段这样的代码。**漏掉任何一段,那个位置显示的就还是旧值,用户看到的就是错误信息。**
### 1.3 框架做了什么?两步建立自动连接
框架能自动同步,靠的是**两步配合**——缺一不可。
**第一步:你在模板里"登记"哪些地方要显示这个变量**
框架的 HTML 模板里,你用 `{{ count }}` 这样的语法来标记"这里要显示 count 的值"
```html
<!-- Vue 模板 -->
<span>购物车:{{ count }} 件</span> <!-- 位置 A:我要显示 count -->
<span>总价:¥{{ count * 99 }}</span> <!-- 位置 B:我也用了 count -->
<span>{{ count > 5 ? '过多' : '正常' }}</span> <!-- 位置 C:我也用了 count -->
```
框架第一次渲染页面时,会把这个"登记关系"记录下来:**位置 A、B、C 都依赖 count**。
**第二步:框架监视变量,变了就查登记表、自动更新**
框架用 JavaScript 内置的 `Proxy`(代理)把你的变量"包裹"起来,让它变成一个"被监视的变量"。当你修改这个变量时,Proxy 会在赋值的同时悄悄多做一件事:通知框架"count 变了"。框架收到通知后,去查第一步的登记表,把 A、B、C 三个位置全部更新。
```
原生 JS
你写 HTML → <span id="counter">3</span>(和变量无任何连接)
你改变量 → count = 4 → 结束,界面毫无反应
你手动补 → document.getElementById('counter').textContent = 4 → 界面才更新
Vue 框架:
你写模板 → <span>{{ count }}</span>(框架记住:这里依赖 count)
你改变量 → count = 4 → Proxy 拦截 → 通知框架 → 框架查登记表 → 自动更新 A/B/C
```
这就是为什么"只有框架才能自动同步"——原生 HTML 里的 `<span>` 和 JS 变量之间根本没有任何连接,框架的模板语法(`{{ }}`)才是建立这条连接的关键。你写了 `{{ count }}`,框架才知道这里要显示 count;框架才能在 count 变化时,精准找到这里并更新它。
👇 **动手点点看**
先选"原生 JavaScript",点"执行"后注意观察——变量改了但界面纹丝不动,你要一步步手动同步每个位置。再切换到"使用框架",同样点"执行"——变量一改,框架自动完成所有步骤,界面立刻跟上。
<WhyNoAutoSyncDemo />
### 1.4 对比:手动同步 vs 自动同步的实际效果
理解了原理之后,我们来看看在一个稍微复杂一点的场景下,手动同步和自动同步的区别有多大。
👇 **动手点点看**
左边是没有框架时的"手动同步"方式——每个显示区域你都需要单独点"同步"按钮来更新。右边是有框架时的"自动同步"方式——你只管点"添加商品",所有显示区域自动更新。试试在左边故意不同步某个区域,看看会发生什么。
<ManualVsAutoSyncDemo />
**这就是前端框架存在的根本原因:给 JavaScript 变量加上"被修改时自动通知界面更新"的能力,消灭手动同步带来的错误。**
---
## 2. 框架的核心思想:用数据描述界面
### 2.1 两种写法的区别
理解了"自动同步"的价值之后,我们来看框架具体是怎么实现的。
在没有框架的时代(比如使用 jQuery),代码是这样写的——你一步一步告诉浏览器该做什么:
```javascript
// 第 1 步:找到页面上 id 为 counter 的元素
var element = document.getElementById('counter')
// 第 2 步:把这个元素的文字内容改成新的值
element.textContent = '4'
// 第 3 步:找到另一个元素,也改掉
document.getElementById('total').textContent = '¥396'
// 第 4 步:如果数量大于 5,还要改状态提示……
```
这种写法叫**命令式(Imperative**——你在"命令"浏览器一步步执行操作。
有了框架之后,代码变成这样——你只描述"界面应该长什么样":
```html
<!-- 我不管这个值怎么更新到页面上的 -->
<!-- 我只说:这里应该显示 count 的值 -->
<span>{{ count }}</span>
<span>总价:¥{{ count * 99 }}</span>
<span v-if="count > 5">商品过多!</span>
```
这种写法叫**声明式(Declarative**——你在"声明"界面的最终状态,至于怎么达到这个状态,框架自己处理。
### 2.2 核心公式:UI = f(State)
所有现代前端框架——不管是 Vue、React 还是 Svelte——都遵循同一个核心思想,可以用一个公式来表达:
> **UI = f(State)**
这个公式的意思是:
- **State(状态)**:你的应用数据。就是 JavaScript 里的那些变量:购物车里有几件商品、用户有没有登录、当前页面是哪个……
- **f(函数)**:框架的渲染机制。它知道怎么把数据变成界面。
- **UI(界面)**:用户在屏幕上看到的最终结果。
**含义**:给定一组数据(State),经过框架的处理(f),就能确定性地得到对应的界面(UI)。数据变了,界面就跟着变。开发者只需要关心数据,不需要关心界面怎么更新。
👇 **动手点点看**
在左边修改数据(State),观察右边的界面(UI)如何自动跟着变化。这就是 `UI = f(State)` 的直观体现。
<DeclarativeFormulaDemo />
### 2.3 为什么声明式比命令式好?
声明式写法的优势在于:
| 对比维度 | 命令式(没有框架) | 声明式(有框架) |
| :--- | :--- | :--- |
| **代码量** | 每个更新都要写具体操作代码 | 只写一次模板,框架自动处理 |
| **出错概率** | 容易漏更新某个地方 | 框架保证所有地方都更新 |
| **可读性** | 代码里混杂着大量 DOM 操作 | 代码清晰地描述界面结构 |
| **维护成本** | 修改一个功能要改很多地方 | 修改数据逻辑即可,界面自动跟随 |
简单说:声明式让你把精力集中在"业务逻辑"(数据怎么变化)上,不用操心"界面怎么更新"这个重复且容易出错的事情。
---
## 3. 响应式系统:框架如何知道数据变了?
### 3.1 什么是"响应式"
前面说了"数据变了,界面自动更新"。但这里有一个技术问题:**JavaScript 本身并没有"变量被修改时自动通知别人"的能力**。
你写 `count = 4`JavaScript 只是把 `count` 的值从 3 改成 4,不会自动告诉任何人。框架需要一种机制来"发现"你修改了数据。
**响应式(Reactivity** 就是这种机制的总称:当数据发生变化时,系统能自动感知到变化,并执行相应的更新操作。
### 3.2 三种不同的实现方式
不同的框架采用了不同的技术方案来实现响应式。这也是 Vue、React、Svelte 之间最根本的区别。
**方式一:代理拦截(Vue 的做法)**
Vue 使用 JavaScript 内置的 `Proxy`(代理)机制。`Proxy` 可以在你读取或修改一个对象的属性时,自动执行一段你指定的代码。
Vue 把你的数据对象用 `Proxy` 包裹起来。当你执行 `count = 4` 时,`Proxy` 会拦截这次写入操作,通知 Vue:"count 的值变了",然后 Vue 去更新所有用到 `count` 的界面部分。
你作为开发者不需要做任何额外的事情——直接赋值就行,Vue 自动感知。
**方式二:显式调用(React 的做法)**
React 不使用 `Proxy`。它要求你必须通过一个专门的函数来修改数据:
```javascript
// React 的写法
const [count, setCount] = useState(0)
// 不能直接写 count = 4React 不会感知到)
// 必须调用 setCount
setCount(4)
```
只有当你调用 `setCount()` 时,React 才知道数据变了,才会去更新界面。如果你直接写 `count = 4`,React 完全不知道,界面不会更新。
这种方式更"显式"——每一次数据变化都是你主动告诉框架的,不会有意外的更新。
**方式三:编译器分析(Svelte 的做法)**
Svelte 采用了完全不同的路线。它有一个编译器(Compiler),在你的代码运行之前,编译器会先分析你的源代码。
当编译器看到你写了 `count += 1` 这样的赋值语句时,它会自动在这行代码后面插入一段"通知界面更新"的代码。也就是说,在代码运行的时候,"通知"这个动作已经被编译器提前安排好了。
你的代码看起来就是普通的 JavaScript 赋值,但编译后的代码里多了更新界面的逻辑。
👇 **动手点点看**
选择不同的框架标签,点击"修改数据",观察每种框架在"引擎盖下"经历了哪些步骤来完成数据变化的检测和界面更新。
<ReactivityMechanismDemo />
### 3.3 三种方式的对比
| 对比维度 | VueProxy 代理) | React(显式调用) | Svelte(编译器) |
| :--- | :--- | :--- | :--- |
| **开发者写法** | 直接赋值 `count = 4` | 必须用 `setCount(4)` | 直接赋值 `count = 4` |
| **感知变化的时机** | 运行时自动拦截 | 开发者主动通知 | 编译时提前插入通知代码 |
| **运行时性能开销** | Proxy 有少量拦截开销 | setState 调度有少量开销 | 几乎没有额外开销 |
| **调试难度** | 中等 | 数据流清晰,较容易 | 需要理解编译后的代码 |
| **适合场景** | 追求开发效率和自然写法 | 追求可预测的数据流 | 追求极致运行性能 |
三种方式没有绝对的好坏。Vue 写起来最自然,React 的数据流最可控,Svelte 的运行性能最好。选择哪个取决于项目的具体需求。
---
## 4. 组件:把界面拆成可复用的小块
### 4.1 为什么要拆?
一个完整的网页可能有导航栏、侧边栏、内容区、搜索框、用户头像、各种按钮……如果所有代码写在一个文件里,这个文件会变得非常长、非常难维护。
**组件(Component** 就是把界面拆分成一个个独立的小块,每个小块管自己的数据、自己的界面、自己的逻辑。
比如一个电商页面可以拆成这些组件:
- `NavBar` 组件:负责顶部导航栏
- `SearchBox` 组件:负责搜索框
- `ProductCard` 组件:负责一张商品卡片
- `ShoppingCart` 组件:负责购物车
每个组件都是独立的。`ProductCard` 不需要知道 `NavBar` 里写了什么代码,它只需要管好自己。
### 4.2 组件的三个好处
**好处一:复用。** 一个 `ProductCard` 组件写好之后,可以在页面上用 100 次——每次传入不同的商品数据,就会渲染出不同的商品卡片。不需要复制粘贴 100 份 HTML 代码。
**好处二:封装。** 组件内部的数据和逻辑是独立的。修改 `SearchBox` 组件的代码,不会影响到 `ProductCard` 组件。多人协作时,不同的人可以同时开发不同的组件,互不干扰。
**好处三:可维护。** 当某个功能出了问题,你可以直接定位到对应的组件去修复,不需要在一个几千行的大文件里翻找。
👇 **动手点点看**
点击左边的组件名称,查看它在页面上对应的区域。注意观察:同一个 `ProductCard` 组件被复用了多次,每次显示不同的数据。
<ComponentTreeDemo />
### 4.3 组件在代码里长什么样?
以 Vue 为例,一个组件就是一个 `.vue` 文件,里面包含三部分:
```html
<!-- ProductCard.vue -->
<template>
<!-- 这里写 HTML 结构 —— 组件的"外观" -->
<div class="card">
<h3>{{ name }}</h3>
<p>价格:¥{{ price }}</p>
<button @click="addToCart">加入购物车</button>
</div>
</template>
<script setup>
// 这里写 JavaScript 逻辑 —— 组件的"行为"
const props = defineProps(['name', 'price'])
function addToCart() {
// 处理"加入购物车"的逻辑
}
</script>
<style scoped>
/* 这里写 CSS 样式 —— 组件的"样式" */
.card {
border: 1px solid #ccc;
padding: 16px;
}
</style>
```
使用这个组件时,就像使用一个自定义的 HTML 标签:
```html
<!-- 在其他地方使用 ProductCard 组件 -->
<ProductCard name="无线耳机" price="299" />
<ProductCard name="机械键盘" price="599" />
<ProductCard name="显示器" price="1999" />
```
三行代码就渲染出了三张不同的商品卡片。
---
## 5. DOM 操作的代价:为什么框架要费这么大力气?
### 5.1 什么是 DOM 操作?
前面提到过 DOM——浏览器把 HTML 解析后生成的树形结构。**DOM 操作**就是用 JavaScript 去修改这棵树上的节点。比如改一段文字、增加一个元素、删除一个元素、修改一个样式。
这些操作本身不复杂,但是浏览器在执行 DOM 操作之后,需要做很多额外的工作才能让屏幕上的显示更新:
1. **重新计算样式**:这个节点以及它的子节点的 CSS 样式是否需要变化?
2. **重新布局(Layout / Reflow**:页面上所有元素的位置和大小需要重新计算。因为一个元素的改变可能影响到其他元素的位置。
3. **重新绘制(Paint**:把计算好的内容画到屏幕上。
这三个步骤每一个都有计算成本。如果你的代码频繁触发 DOM 操作,浏览器就会反复执行这些步骤,页面就会变卡。
👇 **动手点点看**
观察直接操作 DOM 和批量操作 DOM 的耗时对比。当修改次数增多时,"逐个操作"的耗时会急剧上升。
<DomOperationCostDemo />
### 5.2 框架怎么解决这个问题?
既然直接操作 DOM 很昂贵,框架就想办法**减少 DOM 操作的次数**。具体有两种策略:
**策略一:虚拟 DOM + 差异比较(Vue、React 的做法)**
虚拟 DOMVirtual DOM)是一个 JavaScript 对象,它的结构和真实 DOM 树一一对应,但它只存在于内存中,不会触发浏览器的布局和绘制。
当数据变化时,框架的处理流程是:
1. 用 JavaScript 对象创建一棵"新的虚拟 DOM 树",描述数据变化后界面应该长什么样
2. 把这棵新树和旧树做对比(这个过程叫 **Diff**,即差异比较),找出哪些节点发生了变化
3. 只把真正变化的部分应用到真实 DOM 上(这个过程叫 **Patch**,即打补丁)
这样一来,不管数据怎么变化,最终对真实 DOM 的操作总是最少的。
👇 **动手点点看**
点击"修改数据",观察虚拟 DOM 如何对比新旧两棵树,找出变化的节点。注意看最右边的"真实 DOM"——只有真正变化的部分才会闪烁。
<VirtualDomDiffDemo />
**策略二:编译时精确定位(Svelte 的做法)**
Svelte 不使用虚拟 DOM。它的编译器在你写代码时就分析好了:"当 `count` 变化时,需要更新第 3 行的 `<span>` 元素"。运行时直接定位到那个元素去更新,完全不需要对比新旧树。
这种做法跳过了 Diff 步骤,理论上性能更好。但它依赖编译器的分析能力——编译器需要足够聪明才能正确识别出所有需要更新的地方。
---
## 6. 运行时 vs 编译时:框架设计的核心权衡
### 6.1 两个阶段
前端代码从你写下到最终在浏览器里运行,会经过两个阶段:
- **编译时(Compile-time / Build-time**:你的源代码被构建工具(如 Vite、Webpack)处理,转换成浏览器能直接执行的代码。这个过程发生在你的电脑上,在用户打开网页之前。
- **运行时(Runtime)**:转换后的代码在用户的浏览器中执行。框架的核心逻辑(比如虚拟 DOM 的 Diff、响应式的追踪)就在这个阶段工作。
### 6.2 框架在这两个阶段的工作分配
不同框架在这两个阶段分配的工作量不同,这决定了它们的性能特征和包体积:
- **React**:大部分工作在运行时完成。虚拟 DOM 的创建、Diff、Patch 都发生在浏览器中。好处是灵活性高;代价是需要把整个框架的运行时代码(约 40KB)发送给浏览器。
- **Vue**:混合方式。模板在编译时被优化(编译器标记出哪些节点是静态的、不会变化的),但最终的界面更新仍然通过运行时的虚拟 DOM 完成。运行时代码约 30KB。
- **Svelte**:大部分工作在编译时完成。编译器分析你的代码,直接生成精确的 DOM 更新指令。运行时几乎没有框架代码——最终打包出来只有你自己的业务代码。包体积最小。
👇 **动手点点看**
点击不同的框架标签,查看它们在"运行时 ↔ 编译时"光谱上的位置,以及各自在打包体积、运行性能、开发体验上的权衡。
<FrameworkSpectrumDemo />
### 6.3 行业趋势
近几年框架的发展方向很明确:**把越来越多的工作从运行时移到编译时**。因为编译时的计算不占用用户的设备资源,不影响页面加载速度。
- **Vue** 正在开发 Vapor Mode(蒸汽模式),可以跳过虚拟 DOM,在编译时直接生成 DOM 操作代码
- **React** 推出了 React Compiler,在编译时自动优化组件的重渲染行为
- **Svelte 5** 引入了 Runes 系统,进一步增强编译时的分析能力
---
## 7. 总结
回顾这篇文章的核心要点:
**前端框架解决的根本问题**:当应用中的数据发生变化时,自动、高效、可靠地更新界面,不需要开发者手动操作 DOM。
**它们共同遵循的核心思想**UI = f(State)——界面是数据的函数,开发者只需关注数据的变化,框架负责把数据的变化反映到界面上。
**它们的关键技术差异**
| 技术点 | 含义 |
| :--- | :--- |
| **响应式系统** | 框架如何检测数据变化。Vue 用 Proxy 拦截、React 用显式 setState、Svelte 用编译器分析。 |
| **虚拟 DOM** | Vue 和 React 用一个 JavaScript 对象来模拟 DOM 树,通过对比新旧两棵树(Diff)来找出最小更新量,减少真实 DOM 操作。 |
| **组件化** | 把界面拆成独立的、可复用的小块,每个组件管理自己的数据和界面。 |
| **编译时优化** | 在代码构建阶段提前做分析和优化,减少运行时的计算量。Svelte 在这方面走得最远。 |
**一句话**:前端框架的本质工作就是——接管"数据到界面"的同步过程,让开发者只需要思考数据逻辑,不再需要手动操作界面。
---
## 名词对照表
| 英文术语 | 中文对照 | 解释 |
| :--- | :--- | :--- |
| **Framework** | 框架 | 一套预先编写好的代码和规则,为开发者提供应用的基础结构和常用功能。 |
| **DOM** | 文档对象模型 | 浏览器把 HTML 解析后生成的树形数据结构,JavaScript 通过操作它来修改页面。 |
| **Virtual DOM** | 虚拟 DOM | 用 JavaScript 对象模拟 DOM 树,通过 Diff 算法找出最小更新路径,减少真实 DOM 操作次数。 |
| **State** | 状态 | 应用中的数据,比如用户信息、购物车内容、页面当前状态等。 |
| **Reactivity** | 响应式 | 当数据变化时,系统能自动感知并执行对应的界面更新操作。 |
| **Proxy** | 代理 | JavaScript 内置机制,可以拦截对一个对象的读取和写入操作。Vue 3 用它来实现响应式。 |
| **Component** | 组件 | 一段独立的、可复用的界面代码,包含自己的 HTML 结构、JavaScript 逻辑和 CSS 样式。 |
| **Declarative** | 声明式 | 一种编程方式:你描述"最终想要什么结果",由框架来决定怎么实现。 |
| **Imperative** | 命令式 | 一种编程方式:你一步一步告诉程序"具体怎么做"。 |
| **Diff** | 差异比较 | 对比新旧两棵虚拟 DOM 树,找出哪些节点发生了变化。 |
| **Patch** | 打补丁 | 把 Diff 找到的变化部分,应用到真实 DOM 上。 |
| **Compile-time** | 编译时 | 代码在构建阶段被处理的时期,发生在用户打开网页之前。 |
| **Runtime** | 运行时 | 代码在用户浏览器中执行的时期。 |
| **Compiler** | 编译器 | 一个程序,把源代码转换成另一种形式的代码。Svelte 的编译器把 `.svelte` 文件转换成高效的 JavaScript。 |