Svelte
![](https://img.haomeiwen.com/i5387234/5f094bba4fd6818c.png)
借由模板语法的约束,经过 AOT 的编译优化,Svelte 可以直接建立 “自变量与元素的对应关系”。Svelte 在运行时忽略了“根据自变量变化计算出 UI 变化”这一步骤,使其在执行“细粒度的更新”(比如更新大列表的某一行)时比“使用 VDOM 的框架” 的整体更新路径更短。
Vue3
Vue3 是一款组件级别的前端框架,这意味着它会建立“自变量与组件的对应关系”,并在此基础上通过 VDOM 寻找 “自变量变化到UI变化的关系”。同时,由于 Vue3 使用模板语法描述 UI,因此它可以从 AOT 中受益。 Vue3 原理如下:
![](https://img.haomeiwen.com/i5387234/414399f91427151c.png)
Vue3 的代码如下
<script setup>
import { ref } from 'vue'
let count = ref(0);
</script>
<template>
<h1 @click="count ++">{{ count }}</h1>
</template>
Vue3 会对每个组件生成 watchEffect
,在初始化和依赖的变量变化时,会执行
(1). 调用组件的 render 函数,生产 VNode,
// 模板代码
<h1 @click="count++">{{ count }}</h1>
//编译后生成的 render 函数
function render(_ctx, _cache, $props, $setup, $data, $options) {
return (_openBlock(), _createElementBlock("h1", (
onClick: _cache(0) || (_cache(0) = $event => (_ctx.count++))
), _toDisplayString(_ctx.count), 1 /* TEXT */));
}
effect 会订阅“其回调函数上下文中执行的所有自变量”,当自变量发生变化后,effect 会重新执行。所以当上述 render 函数执行后,内部的自变量变化 (_ctx.count 的变化) 会被该 effect 订阅。
(2) 在步骤 (1) 执行后,render 函数的返回值为本次更新的 VNode,它会与上一次更新的 VNode 同时传入 patch 方法,执行 VDOM 的相关操作,找到 “本次自变量变化导致的元素变化”,并最终执行对应的 DOM 操作。
React
作为应用级框架,React 的实现原理很简单,
![](https://img.haomeiwen.com/i5387234/7facf57d3e46726e.png)
- 触发事件,改变自变量,开启更新流程;
- 执行 VDOM 相关操作,在 React 中被称为 reconcile;
- 根据步骤 2 计算出所需要变化的 UI, 执行对应的 UI 操作,在 React 中被称为 commit。
React 被称为应用级框架的原因在于,其每一次更新流程都是从应用的根结点开始的。对比与其他框架:
- Vue3 的更新流程开始于组件。
- Svelte 的更新流程开始于元素。
由于每次都是全更新,React 不关心是哪个自变量发生变化,也不需要 “细粒度更新” 和 AOT。一方面 React 内部有其优化机制,另一方面,React 暴露了一些 API 来减少无意义的遍历过程,比如 shouldComponentUpdate
、React.memo
、PureComponent
。
Vue3 由于细粒度更新和 AOT 优化,已经减少了大部分无意义的遍历过程。可以说: 由于 React 没有完成这部分性能优化的任务,因此这部分工作交到了开发者手中。
相对的,基于“重运行时”架构,React 拓展了许多令人耳目一新的能力,比如:
- 优先级调度
- Time Slice (时间切片)
- Hooks
- Suspense
网友评论