终端用户感知明显的是
-
性能优化
-
Tree-Shaking (摇枝算法)
我摘抄了PPT,看PPT就很详细
Performance(性能优化)
-
Rewritten virtual dom implementation
-
考虑兼容性
-
对于库作者,模板之外,脱离模板,实现逻辑复杂的渲染表达
-
-
Complier-informed fast paths
-
More effcient component initalization
-
1.3 - 2x better update performance
-
2 - 3x faster SSR*
all those thing based on benchmarks simulates typical scenarios ,may vary based on actual application
Tree-Shaking support
https://vue-next-template-explorer.netlify.app/
以上vue3最新的master commit 代码来玩的玩具
如何使用vue-next-template-explorer
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("span", null, "static"), _createVNode("span", null, _toDisplayString(_ctx.msg), 1 /* TEXT */)//1 patchflag flag是编译时生成的一个配置,只有带patchflag的Node(节点)会被追踪,比较text的文字变动 ])) }
<div> <span>static</span> <span> {{msg}} </span> </div>
举例vue2渲染Dom的算法diff例子和vue3渲染Dom的例子
Vue2
<div> <span>static</span> <span>static</span> <span>static</span> <span> {{msg}} </span> <span>static</span> <span>static</span> <span>static</span> <span>static</span> </div>
默认渲染VirtualDom的diff算法是将整棵树的style遍历一次,每一个style的旧Props跟新的Props有什么变化,js快,但是应用大了之后,消耗性能0
而vue3的diff算法是只需检查带有patchflag的节点过一遍就是了
Vue3
<div> <span>static</span> <span>static</span> <span>static</span> <span> <span>{{msg}}</span> </span> <span>static</span> <span>static</span> <span>static</span> <span>static</span> </div>
哪怕这个span是经过嵌套的,vue3仍然不需要遍历,因为加入patchflag的节点会和block(div)节点绑定在一起,所以进入第一句(_openBlock(), _createBlock("div", null,之后就会找到绑定的节点,不需要遍历其他
静态ID绑定
<div> <span id='helloId'> {{msg}} </span> </div>
_createVNode("div", null, [ _createVNode("span", { id: "helloId" }, _toDisplayString(_ctx.msg), 1 /* TEXT */) ]),
静态ID的绑定与双向绑定text的方式无变化
动态ID绑定
<div> <span :id='helloId'> {{msg}} </span> </div>
_createVNode("div", null, [ _createVNode("span", { id: _ctx.helloId }, _toDisplayString(_ctx.msg), 9 /* TEXT, PROPS */, ["id"]) ]),
此时,patchflag产生变化,告诉我们不仅有text文字的变化还有属性props的变化,并且向我们指明是属性id动态变化,目的是让动态更新的时候关注真正变化的东西
Cache Handlers(事件侦听器的缓存)
<div> <span :id='helloId' @click='OnClick'> {{msg}} </span> </div>
//如果不选择 Cache Handlers _createVNode("div", null, [ _createVNode("span", { id: _ctx.helloId, onClick: _ctx.OnClick }, _toDisplayString(_ctx.msg), 9 /* TEXT, PROPS */, ["id", "onClick"]) ]),
//使用Cache Handlers _createVNode("div", null, [ _createVNode("span", { id: _ctx.helloId, onClick: _cache[1] || (_cache[1] = $event => (_ctx.OnClick($event))) }, _toDisplayString(_ctx.msg), 9 /* TEXT, PROPS */, ["id"]) ]),
onClick: cache[1] || (cache[1] = $event => (_ctx.OnClick($event)))
如果当前缓存没有,代表需要从$event传递进来,如果有缓存,直接找到缓存
支持手写内联函数
内联函数也可以缓存进来,当然vue3这边有做分析,至于如何分析,暂时不知道,尤雨溪有讲,如果是在jsx里面这样写,学过jsx之后,去和react做对比
<div> <span :id='helloId' @click='()=>foo()'> {{msg}} </span> </div>
_createVNode("div", null, [ _createVNode("span", { id: _ctx.helloId, onClick: _cache[1] || (_cache[1] = ()=>_ctx.foo()) }, _toDisplayString(_ctx.msg), 9 /* TEXT, PROPS */, ["id"]) ]),
Server Side Rendering
创建静态的标签直接使用字符串式,push进buffer流内,而不用一个一个去createElement
<div>Hello World!</div> <div>Hello World!</div> <div>Hello World!</div> <span>{{msg}}</span> <div>Hello World!</div> <div>Hello World!</div>
import { ssrInterpolate as _ssrInterpolate } from "@vue/server-renderer" export function ssrRender(_ctx, _push, _parent) { _push(`<!--[--><div>Hello World!</div><div>Hello World!</div><div>Hello World!</div><span>${_ssrInterpolate(_ctx.msg)}</span><div>Hello World!</div><div>Hello World!</div><!--]-->`) }
而当你的静态节点嵌套得特别深入,也会创建出一个staticNode去优化
Tree-shaking
-
Most Optional features(e.g v-model,<transition>) are now tree-shakable
-
Bare-bone Hello World size:13.5kb;
-
11.75kb will only Composition API support;
-
-
All runtime features included:22.5kb;
-
More features but still lighter than Vue2 (开关去掉对2.0的支持)
-
treeshaking是通过编译器去实现的,
Composition
尤雨溪并未讲解,如有需求,可去https://composition-api.vuejs.org/网站查看,尤雨溪提及API Reference 中 Reactivity APIs的6个API才是核心API
Fragment
对于模板用户来说,肯定是无感知的。
模板只有一个根节点,在vue3里面无需拥有根节点,可以多行文字,多个节点,而vue3会自动变成一个碎片。而如果用户使用渲染函数,也可以直接在渲染函数中返回一个数组,自动变为碎片
-
No Longer limited to a single root node in templates
-
Manual render functions can simply return Arrays
-
Just works
Teleport
接受一个disbaled参数,将本来应该传送出去的东西驳斥回来,放在原来的渲染函数里面,disalbed 用于响应式的设计,比如宽的屏幕展示出来,窄的屏幕拉回来。
多个Teleport 可以添加内容到同一个Compare里面
-
Previously known as <Portal> React.Portal
-
More details to be shared by @Linusborg
Suspense
suspense 如何用在异步的请求里面。可感知的性能提升是很低的,不作调度的情况下,也能做suspense
它可以在嵌套的组件树渲染到屏幕上之前,可以在内存里面进行渲染,可以检测整颗树里面的异步依赖,只有当将整颗树的异步依赖都渲染完成之后,也就是resolve之后,才会将组件树渲染到屏幕上去。
之前vue的做法并不是这样,vue的组件嵌套是不会在乎你是否渲染完毕
vue3可以将async setup作为异步原语,本身就是这样来做,只要组件内部有一个async的setup函数就会认为该组件是异步组件,也可以不跟suspense绑定
suspense主要是管理一些异步组件的加载也可以
-
Wait on nested async dependecies in a nested tree
-
Works with async setup()
-
Works with Async Components
Better Typescript support
-
Codebase written in TS w/auto-generated type defintions
-
API is the same in JS and TS
-
In fact ,code will also be largely the same
-
-
TSX support
-
Class components is still supported(vue-class-component@next) is currentty in alpha
针对vscode有插件
Custom Renderer API
vite
一个简易的http
服务器,无需webpack
编译打包,根据请求的Vue
文件,直接发回渲染,且支持热更新(非常快)
之后就讲了一些插件的作者和他们联动更新,2.x如何兼容3.0 ,问题不大