Appearance

「初学笔记」Vue3.0(一)

WXL570CN2021/05/31beginner-notesVue Vue3

「初学笔记」Vue3.0(一)

Vue3.0 中文文档open in new windowVue3.0 代码转换open in new window

静态标记(PatchFlag)

Vue3 中仅对会发生变化的虚拟DOM进行标记,该标记称为静态标记

<div>
  <p>Xmo</p>
  <p>Xmo</p>
  <p>Xmo</p>
  <p>{{msg}}</p>
</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, "Xmo"),
    _createVNode("p", null, "Xmo"),
    _createVNode("p", null, "Xmo"),
    _createVNode("p", null, _toDisplayString(_ctx.msg), 1 /* TEXT */)
  ]))
}

上面例子中,Vue3 对 text文本做了静态标记,标记为1

_createVNode("p", null, _toDisplayString(_ctx.msg), 1 /* TEXT */)

因此,Vue3 可以通过不同的标记来得知当前节点要比对的具体内容 {% note success %}当数据发生改变时,Vue2会对虚拟DOM进行全量对比,而Vue3只比对带有 PF 的节点进行对比{% endnote %}

静态提升

Vue3.0 会对未被静态标记的元素做静态提升,这些元素只会被创建一次,在渲染时直接复用

同样的html结构,以下是静态提升之后的效果

const _hoisted_1 = /*#__PURE__*/_createVNode("p", null, "Xmo", -1 /* HOISTED */)
const _hoisted_2 = /*#__PURE__*/_createVNode("p", null, "Xmo", -1 /* HOISTED */)
const _hoisted_3 = /*#__PURE__*/_createVNode("p", null, "Xmo", -1 /* HOISTED */)

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

事件侦听器缓存

OnClick会被视为动态绑定,所以Vue每次更新都会追踪它的变化 但很明显,我们不希望这个属性被标记为动态,直接缓存复用即可

<div>
  <div @click="onClick">click</div>
  <div @click="onClick1">click1</div>
  <input @keyup.enter="submit" />
</div>
export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createBlock("div", null, [
    _createVNode("div", { onClick: _ctx.onClick }, "click", 8 /* PROPS */, ["onClick"]),
    _createVNode("div", { onClick: _ctx.onClick1 }, "click1", 8 /* PROPS */, ["onClick"]),
    _createVNode("input", {
      onKeyup: _withKeys(_ctx.submit, ["enter"])
    }, null, 40 /* PROPS, HYDRATE_EVENTS */, ["onKeyup"])
  ]))
}

可以看到,click被静态标记,标记为8,进行事件侦听器缓存后

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createBlock("div", null, [
    _createVNode("div", {
      onClick: _cache[1] || (_cache[1] = (...args) => (_ctx.onClick && _ctx.onClick(...args)))
    }, "click"),
    _createVNode("div", {
      onClick: _cache[2] || (_cache[2] = (...args) => (_ctx.onClick1 && _ctx.onClick1(...args)))
    }, "click1"),
    _createVNode("input", {
      onKeyup: _cache[3] || (_cache[3] = _withKeys((...args) => (_ctx.submit && _ctx.submit(...args)), ["enter"]))
    }, null, 32 /* HYDRATE_EVENTS */)
  ]))
}

可以发现,静态标记被移除了,但我们还能发现

{% note warn %}只要监听了除了 click 以外的方法,都会添加 32 事件监听静态标记{% endnote %}

Last Updated 2023-04-02 15:01:41