前言🖖
自从Vue3.0
发布后一直想要学习一下新特性,谁曾想到一直鸽到了现在。面对前端行业不学习就被淘汰的内卷环境什么都要学起来呀,学的时候索性记录总结一下。
Vue 3.0亮点🤩
Vue 3.0
性能比Vue 2.x
快 1.2~2倍Tree-Shaking
:按需编译,体积比Vue 2.x
小- 新推出的
Composition API
使组件更易维护 - 更好
TypeScript
支持 Custom Render API
:暴露了自定义渲染API
- 更多先进牛逼的组件
总的来说就是更快更小更舒服.
Vue 3.0到底是如何变快🤔
大家都说Vue 3.0
变快了,那他到底是哪里快了呢?做了哪些优化才会让它有这种效果?
diff算法优化🦄
- 熟悉
Vue 2.x
的兄弟都知道渲染真实DOM
的开销是很大的,比如我们修改某个数据直接渲染在真实DOM
上会引起DOM
树的重排重绘。 - 于是就有了
diff
算法可以根据真实DOM
生成一棵虚拟DOM
树(Virtual DOM
)从而计算出Virtual DOM
中被改变的部分,然后针对该部分进行原生DOM
操作,而不用重新渲染整个页面。
- 值得注意的是
diff
算法是对树的每一层进行遍历从而找出不同进行替换(图片来自网络),而Vue3.0
的diff
算法就在此做出了优化。 - 举个例子说明一下吧,在下面有两个
p
标签一个是不会变的数据一个是绑定的数据,当sth
改变的时候,Vue
会生成新的虚拟DOM
然后和旧的进行对比。
<div> <p>hi 小卢!!</p> <p>{{sth}}</p> </div> 复制代码
在Vue 2.x
中
在Vue 3.0
中
- 从上面的图例可知在
Vue 2.x
中diff
算法会将两棵DOM
树的所有节点进行对比,但实际变化的只有双向绑定的那个。 - 在
Vue 3.0
中会在创建虚拟DOM
的时候将会变化的内容进行静态标记,这样diff
算法的时候直接对比有标记的,对比的少了自然而然速度就变快了。
在Vue 3 Template Explorer中显示如下上面flag
的1是Patchflag
枚举,取值为1代表这个元素的文本是动态绑定的
附录:PatchFlags export const enum PatchFlags {Ⅰ TEXT = 1,1/动态文本节点 CLASS = 1<<1,1/ 2// 动态 classSTYLE= 1<<2,// 4//动态 style PROPS = 1<< 3,// 8// 动态属性,但不包含类名和样式 FULL_PROPS = 1<<4,// 16 //具有动态 key属性,当key改变时,需要进行完整的 diff 比较。 HYDRATE_EVENTS = 1<<5,// 32//带有监听事件的节点 STABLE_FRAGMENT = 1<<6,// 64//一个不会改变子节点顺序的 fragment KEYED_FRAGMENT = 1<<7,// 128//带有key属性的 fragment 或部分子字节有 keyUNKEYED_FRAGMENT = 1<<8,// 256//子节点没有key 的 fragment NEED_ PATCH =1<<9,//512//一个节点只会进行非 props比较 DYNAMIC_SLOTS = 1 << 10,//1024 // 动态的插槽 // SPECIAL FLAGS (下面是特殊的)--------------------------------------------------------- // 以下是特殊的flag,不会在优化中被用到,是内置的特殊flag // 表示他是静态节点,他的内容永远不会改变,对于hydrate的过程中,不会需要再对其子节点进行diff HOISTED = -1, BAIL = -2, // 用来表示一个节点的diff应该结束 } 复制代码
如果想更多了解PatchFlags
可以阅读Vue3的patchFlags超详细讲解
hoistStatic(静态提升)🦓
- 这就好比你每天去便利店买咖啡,每次买的时候店员都问你需要什么,当时间久了店员熟悉了你的习惯就省去了店员问你'要什么'的这个过程,直接给你所需要的商品。
- 顾名思义
静态提升
就是把不参与更新的静态元素给提升出来,说白了就是类似把变量变成常量不进行重新创建
。 - 在
Vue 2.x
中无论元素是否参与更新每次都会重新创建,然后渲染,这对于性能肯定是会有些许损耗。
举个例子说明一下
<div> <div>Hello Vue3.0</div> <div>hi 小卢!</div> <p>{{sth}}</p> </div> 复制代码
未使用静态提升
使用静态提升
- 从上面的两幅对比图可以明显的看到
未使用静态提升
的变量会放在render
函数里面,每次更新数据都会重新创建并渲染出来 - 而
使用了静态提升
的元素会被提取出来放在render
函数外面,这样下次更新的时候就不会把这个元素重新创建,创建的元素少了,自然而然速度也就快起来了。 Vue 3.0
中就是启用了静态提升
把不需要更新的元素放到外面只创建一次,在渲染的时候直接复用即可。
cacheHandlers(事件侦听器缓存)🐲
- 从上面的
diff
算法优化中我们知道,根据PatchFlags
会把动态绑定的元素加上静态标记,那一个事件函数自然就会被加上静态标记,在diff
中会将有标记的元素进行对比来更新数据。 - 如果我们用的这个函数从头到尾都没有改变过,那是不是也可以让它像静态元素一样不进行对比呢?
- 那我都这么问了答案肯定是:可以的!
- 顾名思义事件侦听器缓存就是把没有改变过的事件给侦听到了,然后缓存。
- 就好比刚学
Vue
的你不懂各种api
和优秀的组件,每次用到的时候都会去查看看怎么做,但是当你做久了之后自然你就熟能生巧了,没有得到消息说api
更新了,自然就不会去查找文档对比有什么差异。
举个例子说明一下
<div> <div>Hello Vue3.0</div> <div>hi 小卢!</div> <p>{{sth}}</p> <div @click="doSthing">我是一个点击事件</div> </div> 复制代码
未使用事件侦听器缓存
使用事件侦听器缓存
- 上面转换过的代码如果看不懂的话没有关系,我们只需要观察它是否有静态标记即可。
- 从上面两幅对比图可以看出来在使用了事件监听器缓存的情况下它的静态标记
8
消失了,就说明在Vue 3.0
在每次数据更新时不会对它进行对比了,对比的少了自然而然速度也就加快了
写在最后👌
- 以上就是
Vue 3.0
变快做的一些优化。 - 总的来说
Vue 3.0
通过优化diff
算法让该对比的进行对比,不该对比的不进行对比。 - 通过静态提升和事件侦听缓存来减少不变的元素创建的频率,
加快了
运行速度。 - 如果您觉得这篇文章有帮助到您的的话不妨点赞支持一下哟~~😛