import { createVNode as _createVNode, toDisplaySt._diff静态标记">
赞
踩
第一节:
Vue3 中仅对静态标记标记对象进行比较
- <div>
- <p>Xmo</p>
- <p>{{kkl}}</p>
- <p>Xmo</p>
- <p>1234</p>
- <img :src="img">
- </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, _toDisplayString(_ctx.kkl), 1 /* TEXT */),
- _createVNode("p", null, "Xmo"),
- _createVNode("p", null, "1234"),
- _createVNode("img", { src: _ctx.img }, null, 8 /* PROPS */, ["src"])
- ]))
- }
-
- // Check the console for the AST
可以看到,源码中,对 msg 设计了静态标记,这里是1,后面跟注释 TEXT ,代表这个标签的 TEXT 数据是会动态变化的。(动态变化的东西反而叫静态标记,可还行)
_createVNode("p", null, _toDisplayString(_ctx.msg), 1 /* TEXT */)
对上面的代码开启静态提升(hoistStatic)
开启位置
开启后的效果
- import { createVNode as _createVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createBlock as _createBlock } from "vue"
-
- 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 */),
- _createVNode("img", { src: _ctx.srci }, null, 8 /* PROPS */, ["src"])
- ]))
- }
-
- // Check the console for the AST
将静态内容提取出来,变成常量再进行赋值,只需创建一次,后面直接复用,
非静态提升:每次创建都要重新创建
静态提升:静态内容只需创建一次,后面直接复用
写一段带事件的代码
- <div>
- <button @click="onClick">btn</button>
- </div>
- 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 }, "btn", 8 /* PROPS */, ["onClick"])
- ]))
- }
-
- // Check the console for the AST
这里我们还没有开启事件监听缓存,熟悉的静态标记 8 /* PROPS */
出现了,它将标签的 Props (属性) 标记动态属性。
如果我们存在属性不会改变,不希望这个属性被标记为动态,那么就需要 cacheHandler 的出场了。
开启后
- 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 && _ctx.onClick(...args)))
- }, "btn")
- ]))
- }
-
- // Check the console for the AST
_createVnode 的第二个属性,从
{ onClick: _ctx.onClick }
变为了
{ onClick: _cache[1] || (_cache[1] = (...args) => (_ctx.onClick(...args))) }
它的意思很明显,onClick 方法被存入 cache。在使用的时候,如果能在缓存中找到这个方法,那么它将直接被使用。如果找不到,那么将这个方法注入缓存。总之,就是把方法给缓存了。
- <div>
- <button @click="onClick" @mouseover="onMouseover">btn</button>
- <button @click="onClick1">btn</button>
- </div>
- 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 && _ctx.onClick(...args))),
- onMouseover: _cache[2] || (_cache[2] = (...args) => (_ctx.onMouseover && _ctx.onMouseover(...args)))
- }, "btn", 32 /* HYDRATE_EVENTS */),
- _createVNode("button", {
- onClick: _cache[3] || (_cache[3] = (...args) => (_ctx.onClick1 && _ctx.onClick1(...args)))
- }, "btn")
- ]))
- }
-
- // Check the console for the AST
值得注意的是,在测试过程中,只要监听了除了 click 以外的方法,都会添加 32 /* HYDRATE_EVENTS */
事件监听静态标记(事件的方法静态的,但监听的事件则是动态的【onMouseover是缓存的,而mouseover事件则不是】)。
总之,静态提升之后,事件就不会在 diff 算法中进行比较了。
- export const enum PatchFlags {
- // 动态文字内容
- TEXT = 1,
-
- // 动态 class
- CLASS = 1 << 1,
-
- // 动态样式
- STYLE = 1 << 2,
-
- // 动态 props
- PROPS = 1 << 3,
-
- // 有动态的key,也就是说props对象的key不是确定的
- FULL_PROPS = 1 << 4,
-
- // 合并事件
- HYDRATE_EVENTS = 1 << 5,
-
- // children 顺序确定的 fragment
- STABLE_FRAGMENT = 1 << 6,
-
- // children中有带有key的节点的fragment
- KEYED_FRAGMENT = 1 << 7,
-
- // 没有key的children的fragment
- UNKEYED_FRAGMENT = 1 << 8,
-
- // 只有非props需要patch的,比如`ref`
- NEED_PATCH = 1 << 9,
-
- // 动态的插槽
- DYNAMIC_SLOTS = 1 << 10,
-
- // SPECIAL FLAGS -------------------------------------------------------------
-
- // 以下是特殊的flag,不会在优化中被用到,是内置的特殊flag
-
- // 表示他是静态节点,他的内容永远不会改变,对于hydrate的过程中,不会需要再对其子节点进行diff
- HOISTED = -1,
-
- // 用来表示一个节点的diff应该结束
- BAIL = -2,
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。