Vue3.0快在哪儿?

Vue3.0快在哪儿?

一.diff算法的优化

**vue2:**数据发生变化之后是生成一棵新的DOM树,然后就行全局对比。

如下图:

在这里插入图片描述

**vue3:**新增静态标记(Patch flag)在与上次的虚拟节点进行对比,只对比带有Patch flag的节点并且可以通过flag的信息得知当前节点要对比的具体内容

vue生成虚拟DOM网站

如图:

在这里插入图片描述

附录Patch Flags
export const enum PatchFlags {
    
    
  TEXT = 1,//动态文本节点
  CLASS = 1 << 1,//动态class
  STYLE = 1 << 2,//动态style
  PROPS = 1 << 3,//动态属性
  FULL_PROPS = 1 << 4,//具有动态key属性
  HYDRATE_EVENTS = 1 << 5,//带有监听事件的节点
  STABLE_FRAGMENT = 1 << 6, //一个不会改变子节点顺序的fragment
  KEYED_FRAGMENT = 1 << 7, //带有key属性的fragment或者部分子字节有key
  UNKEYED_FRAGMENT = 1 << 8, //子节点没有key的fragment
  NEED_PATCH = 1 << 9, //一个节点只会进行非props比较
  DYNAMIC_SLOTS = 1 << 10, //动态插槽
  HOISTED = -1,  //静态节点
  BAIL = -2 //提示在diff过程应该退出优化模式
}

二.静态提升(hoist static)

**Vue2:**中无论元素是否参与更新,每次都会重新创建,然后再渲染

**Vue3:**中对于不参与更新的元素,会做静态提升,只会被创建一次,在渲染时直接复用即可

demo

<div>
  <p>我是段落</p>
  <p>{
   
   {msg}}</p>
</div>

vue2.0静态提升前

import {
    
     
	createVNode as _createVNode, 
	toDisplayString as _toDisplayString, 
	openBlock as _openBlock, 
	createBlock as _createBlock 
} from "vue"

export function render(_ctx, _cache, $props, $setup, $data, $options) {
    
    
  return (_openBlock(), _createBlock("div", null, [
    _createVNode("p", null, "我是段落"),
    _createVNode("p", null, _toDisplayString(_ctx.msg), 1 /* TEXT */)
  ]))
}

vue3.0静态提升后

import {
    
    
  createVNode as _createVNode,
  toDisplayString as _toDisplayString,
  openBlock as _openBlock,
  createBlock as _createBlock
} from "vue"

//生成静态节点
const _hoisted_1 = /*#__PURE__*/_createVNode("p", null, "我是段落", -1 /* HOISTED */)

//动态节点
export function render(_ctx, _cache, $props, $setup, $data, $options) {
    
    
  return (_openBlock(), _createBlock("div", null, [
    _hoisted_1,//静态节点复用
    _createVNode("p", null, _toDisplayString(_ctx.msg), 1 /* TEXT */)
  ]))
}

三.事件侦听器缓存(cache handlers)

默认情况下onClick会被视为动态绑定,所以每次都会去追踪它的变化但是因为是同一个函数,所以没有追踪变化,直接缓存起来复用即可

demo

<div>
  <button @click="onClick">按钮</button>
</div>

vue2.0缓存之前

import {
    
    
  createVNode as _createVNode,
  openBlock as _openBlock,
  createBlock as _createBlock
} from "vue"

export function render(_ctx, _cache, $props, $setup, $data, $options) {
    
    
  return (_openBlock(), _createBlock("div", null, [
    _createVNode("button", {
    
     onClick: _ctx.onClick }, "按钮", 8 /* PROPS */, ["onClick"])
  ]))//UNKEYED_FRAGMENT = 1 << 8:有静态标记当做动态属性每次更新进行对比
}

vue3.0缓存之后

import {
    
    
  createVNode as _createVNode,
  openBlock as _openBlock,
  createBlock as _createBlock
} from "vue"

export function render(_ctx, _cache, $props, $setup, $data, $options) {
    
    
  return (_openBlock(), _createBlock("div", null, [
    _createVNode("button", {
    
    
      onClick: _cache[1] || (_cache[1] = (...args) => (_ctx.onClick(...args)))
    }, "按钮")
  ]))//没有了静态标记不会更新后在进行对比
}

**注意点:**转换之后的代码,大家可能还看不懂,但是不要紧,我们只需要观察有没有静态标记即可,因为我们知道在Vue3的diff算法中,只有有静态标记的才会进行比较,才会进行追踪

四.ssr渲染(服务器端渲染)

  • 当有大量静态内容时候,这些内容会被当做纯字符串推进一个buffer里面,即使存在动态绑定,会通过模板插值嵌入进去。这样会比通过虚拟dom来渲染的快上很多很多。

  • 当静态内容大到一定量级时候,会用_createStaticVNode方法在客户端生成一个static node,这些静态node,会被直接innerHTML,就不需要创建对象,然后根据对象渲染。

猜你喜欢

转载自blog.csdn.net/lyf976229437/article/details/109226092
今日推荐