vue3性能提升的方面(对比vue2)

一、静态提升(hoistStatic)

当使用hoistStatic时,所有 静态的节点都被提升到render方法之外。这意味着,他们只会在应用启动的时候被创建一次,而后随着每次的渲染被不停地复用。

示例如下:

<div>
	<p>你好p>
	<p>{{userName}}p>
div>
// 静态提升
const _hoisted_1 = /*#__PURE__*/_createVNode("p", null, "你好", -1 /* HOISTED */)
 
export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createBlock(_Fragment, null, [
    _hoisted_1,
    _createVNode("p", null, _toDisplayString(_ctx.userName), 1 /* TEXT */)
  ], 64 /* STABLE_FRAGMENT */))
}
 

二、预字符串化

在平时vue开发过程中,组件当中没有特别多的动态元素,大多都是静态元素。
一般可以说是动静比,动态内容 / 静态内容,比例越小,静态内容越多,比例越大,动态内容越多。
vue3的编译器它会非常智能地发现这一点,当编译器遇到大量连续的静态内容,会直接将它编译为一个普通字符串节点,因为它知道这些内容永远不会变化,都是静态节点。

注意:必须是大量连续的静态内容才可以预字符串化哦,切记!目前是连续20个静态节点才会预字符串化


  <div>
    <div>
      <h1>法医h1>
    div>
    <p>...20...p>
  div>
// 直接预字符串化,避免创建虚拟dom
const hoistStatic = createStatticVNode('

法医

...20个...

'
) render() { return (openBlock(), createBlock('div', null, [hoistStatic])) }

三、缓存事件处理函数


// vue2处理方式render(ctx){
    return createVNode("button",{
        onclick:function($event){
            ctx.count++;
        }
    })
}

//vue3 处理方式render(ctx,_cache){
    return createVNode("button",{
        onclick:cache[0] || (cache[0] =>($event) =>(ctx.count++))
    })
}

在vue2中创建一个虚拟节点button,属性里面多了一个事件onclick,内容就是count++。在vue3中会认为这里的事件处理是不会变化的,不是说这次渲染是事件函数,下次就变成别的,于是vue3会智能地发现这一点,会做缓存处理,它首先会看一看缓存里面有没有这个事件函数,有的话直接返回,没有的话就直接赋值为一个count++函数,保证事件处理函数只生成一次。

四、Block Tree

理解的不多
其实就是把那些DOM结构可能发生改变的地方也作为一个动态节点进行收集。

五、PatchFlag

在之前的VDOM中,如果msg值发生改变,整个模版中的所有元素都需要重新渲染。但在Vue3.0中,在这个模版编译时,编译器会在动态标签末尾加上 /* Text*/ PatchFlag。只能带patchFlag 的 Node 才被认为是动态的元素,会被追踪属性的修改。并且 PatchFlag 会标识动态的属性类型有哪些,比如这里 的TEXT 表示只有节点中的文字是动态的。

每一个Block中的节点,就算很深,也是直接跟Block一层绑定的,可以直接跳转到动态节点而不需要逐个逐层遍历。

既有VDOM的灵活性,又有性能保证。

示例如下:

<div>
	<p>测试内容p>
	<p>测试内容p>
	<p>{{msg}}p>
div>
// 表示类型
export const enum PatchFlags {
  TEXT = 1,// 动态的文本节点
  CLASS = 1 << 1,  // 2 动态的 class
  STYLE = 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
  UNKEYED_FRAGMENT = 1 << 8, // 256 子节点没有 key 的 Fragment
  NEED_PATCH = 1 << 9,   // 512
  DYNAMIC_SLOTS = 1 << 10,  // 动态 solt
  HOISTED = -1,  // 特殊标志是负整数表示永远不会用作 diff
  BAIL = -2 // 一个特殊的标志,指代差异算法
}

export function render(_ctx, _cache) {
 return (_openBlock(),
 	_createBlock('div',null,[
		_createVNode('p',null,'测试内容'),
		_createVNode('p',null,'测试内容'),
		_createVNode('p',null,_toDisplayString(_ctx.msg),1 /**TEXT*/),
		]
	)
 )
}

你可能感兴趣的:(vue,javascript,前端,vue.js)