文章首发公众号:萌萌哒草头将军
演示源码和在线演示地址,公众号回复”演示“获得
Vapor Mode
是尤雨溪在2022 Year In Review给定相中提出的概念,本篇文章我们将直观感受下尤雨溪为啥要推出Vapor Mode
。
💎前情提要
在前面两篇文章中反复提到了不同框架编译之后的差异
- 🚀 React编译之后是
Jsx
函数返回的虚拟DOM
- 🚀 Vue编译之后是
render
函数返回的虚拟DOM
- 🚀 SolidJS编译之后返回的
真实DOM
字符串 - 🚀 Svelte编译之后返回的是
真实DOM
片段
React
由于架构机制决定了每当状态发生改变,从当前组件开始一直到叶子组件重新加载。
Vue
由于给每个组件建立了watchEffect
监听机制,每当组件依赖的状态发生改变,当前组件重新加载。
SolidJS
和Svelte
由于在编译之后就确定了当状态发生改变UI
随之变化的关系,所以仅仅是具体DOM
的重新加载。
根据这些不同的更新粗细粒度,他们被分为
粒度 | 成员 |
---|---|
粗粒度 | React |
中粒度 | Vue |
细粒度 | SolidJS ,Svelte |
💎直观感受
为了直观感受更新时的区别,现在我们设计如下关系的组件:
GrandFather
|
Father
|
Child
每个组件的背景色都是随机的,并且在Father
组件中,实现了一个Count
功能。
我们用四个框架分别实现。下面只给出一个例子。
生成随机颜色:
`#${(~~(Math.random()*(1<<24))).toString(16)}`
Father
组件如下:
// Father.jsx
import React, { useState } from 'react'
const Father = () => {
const [count, setCount] = useState(0)
const onClick = () => setCount(count => count ++)
return (
<div style={{ display: "flex" }}>
<div
onClick={() => onClick()}
style={{
height: 100,
width: `40vw`,
background: `#${(~~(Math.random() * (1 << 24))).toString(16)}`,
}}
>
{count}
<Child />
</div>
<div
onClick={() => onClick()}
style={{
height: 100,
width: `40vw`,
background: `#${(~~(Math.random() * (1 << 24))).toString(16)}`,
}}
></div>
</div>
)
}
export default Father
接下来,我们看看他们在触发onClick
时的不同表现吧。
🚀 React
🚀 Vue
🚀 Svelte
🚀 SolidJS
🚀 结论
上面的图中,可以直观的看到:
React
在当前组件状态发生变化时,从当前组件开始,包括子组件都被重新加载了。
Vue
仅仅是当前组件重新加载。
SolidJS
、Svelte
仅仅是重新加载组件!
💎总结
在项目比较小时,SolidJS
、Svelte
的优势不会很明显,
但是当面对大型项目时,React
和Vue
的性能短板就显露出来了。
面对这样的压力,尤雨溪在年初的展望里已经预告了Vapor mode
,该模式的灵感就是受到了SolidJS
的启发。
它可以在给定相同的Vue SFC
前提下,与当前基于虚拟DOM
的输出相比,Vapor Mode
将其编译成性能更高、使用更少内存且需要更少运行时支持代码的JavaScript
输出。
对于React
由于架构机制的限制,目前很难做出根本性的改变,
对于开发者,我们可以选择手动优化。例如,将组件使用memo
包裹起来。
const Child = memo(() => <Comp>your comp</Comp>)
此时上面的例子中,React
的效果更新效果就和Vue
类似了。
我们为了演示每次dom
都是重新加载的,所以样式是直接这样写的。
background: `#${(~~(Math.random() * (1 << 24))).toString(16)}`
在实际开发中,要尽量避免无意义的重复计算,尤其React
中,比如:
// bad
<Comp
style={
margin: window.screen.width / 3 * 2
}
/>
// good
const App = () => {
const margin = useMemo(() => window.screen.width / 3 * 2, [])
return <Comp style={ margin } />
}
// bettter
const margin = window.screen.width / 3 * 2
const App = () => {
return <Comp style={ margin } />
}
好了今天的分享就到这了,文章中如果出现问题,有劳各位大佬指正!
原文链接:https://juejin.cn/post/7238153003282513957 作者:萌萌哒草头将军