vue3.0 是如何变快的?

diff算法优化

Vue2中的虚拟 dom 是进行全量的对比
Vue3新增了静态标记(PatchFlag)
在与上次虚拟节点进行对比时候,只对比带有 patch flash 的节点
并且可以通过 flag 的信息得知当前节点要对比的具体内容

vue2.0 代码转换
vue3.0代码转换

vue2.0转换

<div>
  <p>我是段落</p>
  <p>我是段落</p>
  <p>我是段落</p>
  <span>{{msg}}</span>
</div>
function render() {
  with(this) {
    return _c('div', [_c('p', [_v("我是段落")]), _c('p', [_v("我是段落")]), _c('p', [
      _v("我是段落")
    ]), _c('span', [_v(_s(msg))])])
  }
}

vue3.0转换

<div>
  <p>我是段落</p>
  <p>我是段落</p>
  <p>我是段落</p>
  <span>{{msg}}</span>
</div>
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, "我是段落"),
    _createVNode("p", null, "我是段落"),
    _createVNode("span", null, _toDisplayString(_ctx.msg), 1 /* TEXT */)
  ]))
}
// Check the console for the AST

hoistStatus静态提升

Vue2中无论元素是否参与更新,每次都会重新创建,然后渲染
Vue3对于不参加更新的元素,会做静态提升,只会被创建一次,在渲染时直接复用第一次创建的,以达到性能提升,速度变快…

<div>
  <p>我是段落</p>
  <p>我是段落</p>
  <p>我是段落</p>
  <span>{{msg}}</span>
</div>
import { createVNode as _createVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createBlock as _createBlock } from "vue"

const _hoisted_1 = /*#__PURE__*/_createVNode("p", null, "我是段落", -1 /* HOISTED */)
const _hoisted_2 = /*#__PURE__*/_createVNode("p", null, "我是段落", -1 /* HOISTED */)
const _hoisted_3 = /*#__PURE__*/_createVNode("p", null, "我是段落", -1 /* HOISTED */)

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createBlock("div", null, [
    _hoisted_1,
    _hoisted_2,
    _hoisted_3,
    _createVNode("span", null, _toDisplayString(_ctx.msg), 1 /* TEXT */)
  ]))
}

// Check the console for the AST

cacheHandlers事件侦听器缓存

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

<div>
  <button @onclick="myFn">按钮</button>
</div>

未开启事件监听缓缓存

function render() {
  with(this) {
    return _c('div', [_c('button', {
      on: {
        "onclick": myFn
      }
    }, [_v("按钮")])])
  }
}

开启事件监听缓存

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", {
      onOnclick: _cache[1] || (_cache[1] = (...args) => (_ctx.myFn && _ctx.myFn(...args)))
    }, "按钮", 32 /* HYDRATE_EVENTS */)
  ]))
}

// Check the console for the AST

评论