由于前几天 vue3 从 alpha 过渡到了 beta 版本,意味着 Vue3 已经趋于稳定。今天晚上尤大就关于Vue3 beta 版本的发布做了一次分享。主要是对比了 Vue2 到 Vue3 的性能提升。另外介绍了 Tree Shaking 的优化、编译速度、SSR 渲染优化等方面。 下面就以尤大分享内容做一个总结。
Performance
在性能方面,PPT 介绍了五个方面
- 重写虚拟DOM的实现
- 编译模版的优化
- 更高效的组件初始化
- 更快的的更新时间
- 2到3倍的SSR渲染
在尤大的演示中,看到确实对DOM的编译有了很大的提升。在创建很多的元素节点时,编译时会自动跳过静态节点。静态元素或属性不去做二次渲染。在嵌套层级很深的节点时,也会自动跳过不需要渲染的节点。具体来说,将 virtual dom 编译为 render function 的时候,动态的部分会带有一个 pathFlag 的节点,在做 dom patch 的时候,有 pathFlag 的节点才会做 diff 比较。
import { createVNode as _createVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createBlock as _createBlock } from "vue"
export function render(_ctx, _cache) {
return (_openBlock(), _createBlock("div", null, [
_createVNode("div", null, [
_createVNode("div", null, [
_createVNode("span", null, "hello"),
_createVNode("span", null, "hello"),
_createVNode("span", null, _toDisplayString(_ctx.text), 1 /* pathFlag,TEXT */),
_createVNode("span", null, "hello"),
_createVNode("span", null, "hello"),
_createVNode("span", null, "hello")
])
])
]))
}
// Check the console for the AST
cacheHandlers 是针对模版的事件做的优化,一般情况下,vue 无法判断模版中的事件侦听函数是否是动态的,所以在render函数里面会默处理成动态 props 。但是在启用侦听优化下,render函数会把我们的事件缓存起来,二次调用的时候会直接取缓存的函数。
import { toDisplayString as _toDisplayString, createVNode as _createVNode, openBlock as _openBlock, createBlock as _createBlock } from "vue"
export function render(_ctx, _cache) {
return (_openBlock(), _createBlock("div", null, [
_createVNode("div", null, [
_createVNode("div", null, [
_createVNode("span", {
onClick: _cache[1] || (_cache[1] = () => _ctx.fn())
}, _toDisplayString(_ctx.text), 1 /* TEXT */)
])
])
]))
}
// Check the console for the AST
SSR 中, 如果有大量的HTML 元素时,会自动把这些静态元素 push 进缓存里面。只有存在动态的内容,才会进行动态渲染。这比 React 基于 virtual dom 的整体渲染要快上一个量级。
import { ssrInterpolate as _ssrInterpolate } from "@vue/server-renderer"
export function ssrRender(_ctx, _push, _parent) {
_push(`<div><div><div><span>hello</span><span>hello</span><span>${_ssrInterpolate(_ctx.text)}</span><span>hello</span><span>hello</span><span>hello</span></div></div></div>`)
}
// Check the console for the AST
TreeShaking
TreeShaking 是在 webpack 中存在一项优化措施,webpack 在编译打包的时候,不会导入没有用到的 modules,但是使用限制是模块必须是用 ES6 的 imoport 导入的才可以被 treeShaking 。vue3里内置的有treeShaking功能。比如有些组件没有用到 translation v-model ,在渲染到时候就不会导入这些功能。一言以蔽之。保存vue最核心的功能,其余的只在有需要的时候才会被加载进来。
Componsition API
组合API是Vue3的新的设计理念。在vue2中,所有的逻辑是基于 options ,比如 data 专门放初始化数据,
methods 放事件方法,computed 里面处理计算属性。这样处理方式在中小型应用里面比较简洁清晰,但是当vue 应用逐渐变大后,选项里面的各种逻辑都会参杂在一起。所以vue3 参考 react 提出了 逻辑优先的概念。统一逻辑的处理入口是 setup() 各个逻辑会统一处理,最终 export 需要的属性和方法。
Fragment, Teleport, Suspence
Fragment : 这项在vue3 中体现出来的是,在创建模版文件时不用把所有的元素包裹在div里面,任何一个html 元素都可以单独做一个组件的根结点,甚至一段纯文本也可以。比如:
<template> hello world </template>Teleport 对标
React portal它可以在DOM树中的其他位置呈现组件,即使该位置不在应用程序的范围内,举个例子。如果我们有一个弹窗或者loading组件。这个组件是游离在dom元素之外。在之前的情况下,我们需要设置position,z-index等属性让它看起来脱离于DOM元素,现在只需要用portal就能完成这一效果。简化了特殊元素的样式设置。<!-- In some nested Vue component --> <NestedComponent> <Portal target="#popup-target"> <PopUp /> </Portal> </NestedComponent> <!-- before closing body tag --> <div id="popup-target"></div>suspence 是一个异步加载的机制,在vue 中 经常的场景是:我们需要在异步获取数据之前展示loading 或者 其他等待的逻辑。我们不希望在用户获取数据之前就展示组件,那么 suspence 就很好的解决了这个问题。
<Suspense> <template #default> <UserProfile /> </template> <template #fallback> <div>Loading...</div> </template> </Suspense>我们不需要在逻辑里面写一些类似于
v-if异步加载的判断语句, 并且还可以进行错误的捕获。 ```vue{{ error }} ``` 内容参考自:https://vueschool.io/articles/vuejs-tutorials/suspense-new-feature-in-vue-3/<UserProfile /><div>Loading...</div>Better TypeScript support
vue3提供了更好的TS支持,因为本身的源码就是用
typescript写的。能够跟ts更好的集成,即使不用typescript,用Javascript 同样也能够获得很好的语法提示。同时支持 TSX 的语法编写。Custom Renderer API
不是很了解,后续补充。
