Skip to content

什么是 HoistStatic 和 CacheHandler

都是优化手段

什么是 HoistStatic

  • 将静态节点的定义,提升到父作用域,缓存起来
  • 多个相邻的静态节点,会被合并起来
  • 典型的拿空间换时间的优化策略

还是来看下 https://vue-next-template-explorer.netlify.app/ 这个

html
<div>
  <span>hello vue3</span>
  <span>hello vue3</span>
  <span>hello vue3</span>
  <span>hello vue3</span>
  <span>hello vue3</span>
  <span>hello vue3</span>
  <!-- <span>hello vue3</span>
  <span>hello vue3</span>
  <span>hello vue3</span>
  <span>hello vue3</span>
  <span>hello vue3</span>
  <span>hello vue3</span> -->
  <span>{{msg}}</span>
</div>

生成 AST 树

js
import {
  createElementVNode as _createElementVNode,
  toDisplayString as _toDisplayString,
  openBlock as _openBlock,
  createElementBlock as _createElementBlock,
} from 'vue';

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (
    _openBlock(),
    _createElementBlock('div', null, [
      _createElementVNode('span', null, 'hello vue3'),
      _createElementVNode('span', null, 'hello vue3'),
      _createElementVNode('span', null, 'hello vue3'),
      _createElementVNode(
        'span',
        null,
        _toDisplayString(_ctx.msg),
        1 /* TEXT */,
      ),
    ])
  );
}

// Check the console for the AST

然后在 Options 里勾选 hoistStatic, AST 树变化

将静态节点的定义,提升到父作用域,缓存起来

js
import {
  createElementVNode as _createElementVNode,
  toDisplayString as _toDisplayString,
  openBlock as _openBlock,
  createElementBlock as _createElementBlock,
} from 'vue';

const _hoisted_1 = /*#__PURE__*/ _createElementVNode(
  'span',
  null,
  'hello vue3',
  -1 /* HOISTED */,
);
const _hoisted_2 = /*#__PURE__*/ _createElementVNode(
  'span',
  null,
  'hello vue3',
  -1 /* HOISTED */,
);
const _hoisted_3 = /*#__PURE__*/ _createElementVNode(
  'span',
  null,
  'hello vue3',
  -1 /* HOISTED */,
);

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

// Check the console for the AST

多个相邻的静态节点,会被合并起来

js
import {
  createElementVNode as _createElementVNode,
  toDisplayString as _toDisplayString,
  createStaticVNode as _createStaticVNode,
  openBlock as _openBlock,
  createElementBlock as _createElementBlock,
} from 'vue';

const _hoisted_1 = /*#__PURE__*/ _createStaticVNode(
  '<span>hello vue3</span><span>hello vue3</span><span>hello vue3</span><span>hello vue3</span><span>hello vue3</span><span>hello vue3</span><span>hello vue3</span><span>hello vue3</span><span>hello vue3</span><span>hello vue3</span><span>hello vue3</span><span>hello vue3</span>',
  12,
);

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (
    _openBlock(),
    _createElementBlock('div', null, [
      _hoisted_1,
      _createElementVNode(
        'span',
        null,
        _toDisplayString(_ctx.msg),
        1 /* TEXT */,
      ),
    ])
  );
}

// Check the console for the AST

什么是 CacheHandler

继续 https://vue-next-template-explorer.netlify.app/ 这个

html
<div>
  <span @click="clickHandler">hello vue3</span>
</div>

生成 AST 树

js
import {
  createElementVNode as _createElementVNode,
  openBlock as _openBlock,
  createElementBlock as _createElementBlock,
} from 'vue';

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (
    _openBlock(),
    _createElementBlock('div', null, [
      _createElementVNode(
        'span',
        { onClick: _ctx.clickHandler },
        'hello vue3',
        8 /* PROPS */,
        ['onClick'],
      ),
    ])
  );
}

// Check the console for the AST

然后在 Options 里勾选 cacheHandlers, AST 树变化

通过 _cache[0] 缓存函数

js
import {
  createElementVNode as _createElementVNode,
  openBlock as _openBlock,
  createElementBlock as _createElementBlock,
} from 'vue';

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (
    _openBlock(),
    _createElementBlock('div', null, [
      _createElementVNode(
        'span',
        {
          onClick:
            _cache[0] ||
            (_cache[0] = (...args) =>
              _ctx.clickHandler && _ctx.clickHandler(...args)),
        },
        'hello vue3',
      ),
    ])
  );
}

// Check the console for the AST

基于 MIT 许可发布