Svelte 运行时系统负责处理 Svelte 应用中的响应式、组件生命周期、DOM 操作和渲染。它弥合了编译器生成的优化 JavaScript 与实际 DOM 更新之间的差距。本页面解释了运行时系统的核心架构和机制,重点关注响应式、副作用和 DOM 操作如何协同工作。
有关将 Svelte 组件转换为使用此运行时生成的 JavaScript 的编译器信息,请参阅 编译器架构。
Svelte 运行时系统是一个小巧、高效的层,它提供了
此运行时采用精细的响应式系统,仅更新需要更改的 DOM 部分,避免了虚拟 DOM diffing 方法的开销。
来源
Svelte 的响应式系统围绕三个核心基元构建
源是 Svelte 响应式系统的基础。它们代表可读写的可变值。当源更改时,所有依赖于它的副作用都会被调度执行。
source() 函数创建了一个简单的响应式值,而 mutable_source() 创建了一个具有特殊相等性检查(用于数组和对象)的响应式值。
来源
派生值是从一个或多个源计算得出的。它们是惰性求值的,并且仅当其依赖项发生更改且实际读取它们时才重新计算。
派生值会自动跟踪其依赖项。当派生值被读取时,它会在其计算过程中将自己注册为读取的任何源的依赖项。
来源
副作用是依赖项更改时运行的函数。有几种类型的副作用
$effect) - 依赖项更改时运行,用于副作用副作用通过记录执行过程中读取的源和派生值来自动跟踪其依赖项。
来源
副作用系统是一个分层的副作用树,它管理响应式更新何时以及如何发生。副作用被组织成一个树形结构
$effect() 的自定义副作用每个副作用可以有子副作用,形成一个树。当一个副作用被调度运行时,它会按顺序处理其子项。
来源
当源发生变化时,所有依赖于它的副作用都会被标记为脏,并被调度执行。运行时系统利用微任务智能地批量处理这些更新,以提高效率。
副作用更新过程遵循以下步骤
来源
组件在生命周期中经历几个阶段
组件挂载时,mount() 函数会创建一个根副作用,该副作用执行组件函数。这会设置初始 DOM 结构和响应式。
来源
当状态更改时,响应式系统会将副作用标记为脏并调度它们运行。这导致组件仅更新依赖于已更改状态的部分。
来源
组件卸载时,其根副作用会被销毁。这将递归地销毁所有子副作用,移除事件监听器,并可以选择运行退出过渡。
来源
Svelte 直接操作 DOM,而不是使用虚拟 DOM。它结合使用了模板函数和基于副作用的更新。
模板是根据 HTML 字符串创建 DOM 节点的函数。Svelte 将组件模板编译成高效的 JavaScript,用于创建和更新 DOM 元素。
来源
DOM 操作是直接操作 DOM 的函数。这些包括
这些操作由响应状态变化的副作用触发。
来源
水合是将客户端运行时连接到服务器渲染的 HTML 的过程。Svelte 使用特殊的标记注释来将客户端组件结构与服务器渲染的 DOM 匹配。
来源
控制流块是处理条件渲染(if)、列表(each)、异步数据(await)等的特殊组件。每种块类型在运行时都有其自己的实现。
If 块根据值有条件地渲染内容。它们使用副作用来跟踪条件的更改并相应地更新 DOM。
来源
Each 块渲染项目列表。它们能够以最少的 DOM 操作高效地处理添加、删除和重新排序。
来源
Await 块处理异步数据,显示待处理、已完成或已拒绝的 Promise 的不同内容。
来源
关键 Blocks 在其值发生变化时强制重新渲染,这对于动画和过渡非常有用。
来源
Svelte 使用 JavaScript 的 Proxy 来实现对象和数组的深度响应性。当一个对象被设置为响应式时,它会被包裹在一个 Proxy 中,该 Proxy 会拦截属性的访问和修改。
来源
运行时包含强大的错误处理机制,用于捕获和报告在组件渲染或效果执行期间发生的错误。它使用错误边界将错误限制在组件内部。
来源
运行时提供了多种工具函数,支持核心的响应性和 DOM 操作。
flushSync() - 同步处理所有待处理的更新tick() - 返回一个 Promise,该 Promise 在待处理的更新完成后解析untrack() - 运行代码而不跟踪响应式依赖snapshot() - 创建一个值的非响应式副本这些工具可以帮助开发者控制运行时系统的时序和行为。
来源
Svelte 运行时系统是一个复杂而精简的系统,可有效管理响应性、效果和 DOM 更新。通过使用细粒度的响应性和直接的 DOM 操作,它在保持开发者简单心智模型的同时实现了高性能。
该运行时围绕着源、派生值和效果的核心概念构建,所有这些都组织在一个分层树结构中,可以实现高效的更新。这种架构使 Svelte 能够以最小的开销提供响应式的用户体验。