You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
exportfunctionrender(_ctx,_cache,$props,$setup,$data,$options){return(_openBlock(),_createBlock(_Fragment,null,[_createVNode("span",null,"你好"),_createVNode("div",null,_toDisplayString(_ctx.message),1/* TEXT */)],64/* STABLE_FRAGMENT */))}
做了静态提升之后
const_hoisted_1=/*#__PURE__*/_createVNode("span",null,"你好",-1/* HOISTED */)exportfunctionrender(_ctx,_cache,$props,$setup,$data,$options){return(_openBlock(),_createBlock(_Fragment,null,[_hoisted_1,_createVNode("div",null,_toDisplayString(_ctx.message),1/* TEXT */)],64/* STABLE_FRAGMENT */))}// Check the console for the AST
一、编译阶段
回顾
Vue2
,我们知道每个组件实例都对应一个watcher
实例,它会在组件渲染的过程中把用到的数据property
记录为依赖,当依赖发生改变,触发setter
,则会通知watcher
,从而使关联的组件重新渲染试想一下,一个组件结构如下图
可以看到,组件内部只有一个动态节点,剩余一堆都是静态节点,所以这里很多
diff
和遍历其实都是不需要的,造成性能浪费因此,
Vue3
在编译阶段,做了进一步优化。主要有如下:diff算法优化
vue3
在diff
算法中相比vue2
增加了静态标记关于这个静态标记,其作用是为了会发生变化的地方添加一个
flag
标记,下次发生变化的时候直接找该地方进行比较下图这里,已经标记静态节点的
p
标签在diff
过程中则不会比较,把性能进一步提高关于静态类型枚举如下
静态提升
Vue3
中对不参与更新的元素,会做静态提升,只会被创建一次,在渲染时直接复用这样就免去了重复的创建节点,大型应用会受益于这个改动,免去了重复的创建操作,优化了运行时候的内存占用
没有做静态提升之前
做了静态提升之后
静态内容
_hoisted_1
被放置在render
函数外,每次渲染的时候只要取_hoisted_1
即可同时
_hoisted_1
被打上了PatchFlag
,静态标记值为 -1 ,特殊标志是负整数表示永远不会用于 Diff事件监听缓存
默认情况下绑定事件行为会被视为动态绑定,所以每次都会去追踪它的变化
没开启事件监听器缓存
开启事件侦听器缓存后
上述发现开启了缓存后,没有了静态标记。也就是说下次
diff
算法的时候直接使用SSR优化
当静态内容大到一定量级时候,会用
createStaticVNode
方法在客户端去生成一个static node,这些静态node
,会被直接innerHtml
,就不需要创建对象,然后根据对象渲染编译后
二、源码体积
相比
Vue2
,Vue3
整体体积变小了,除了移出一些不常用的API,再重要的是Tree shanking
任何一个函数,如
ref
、reavtived
、computed
等,仅仅在用到的时候才打包,没用到的模块都被摇掉,打包的整体体积变小三、响应式系统
vue2
中采用defineProperty
来劫持整个对象,然后进行深度遍历所有属性,给每个属性添加getter
和setter
,实现响应式vue3
采用proxy
重写了响应式系统,因为proxy
可以对整个对象进行监听,所以不需要深度遍历length
属性关于这两个 API 具体的不同,我们下篇文章会进行一个更加详细的介绍
参考文献
The text was updated successfully, but these errors were encountered: