The v-show Directive
Consider a component like the following.
vue
<script setup>
import { ref } from "vue";
const flag = ref("");
</script>
<template>
<p v-show="flag">Hello, v-show!</p>
</template>
Compilation Result and Overview
The compilation result is as follows.
js
const _sfc_main = {
vapor: true,
__name: "App",
setup(__props, { expose: __expose }) {
__expose();
const flag = ref("");
const __returned__ = { flag, ref };
Object.defineProperty(__returned__, "__isScriptSetup", {
enumerable: false,
value: true,
});
return __returned__;
},
};
import {
vShow as _vShow,
withDirectives as _withDirectives,
template as _template,
} from "vue/vapor";
const t0 = _template("<p>Hello, v-show!</p>");
function _sfc_render(_ctx) {
const n0 = t0();
_withDirectives(n0, [[_vShow, () => _ctx.flag]]);
return n0;
}
What stands out is the part _withDirectives(n0, [[_vShow, () => _ctx.flag]]);
.
Continuing from last time, it uses the withDirectives
function again, but this time it uses the vShow
function as the runtimeDirective.
Reading the Compiler
We will follow transformElement
-> buildProps
-> transformProps
-> directiveTransform
-> transformVShow
.
It's very simple, so I'll include the entire text.
1import { DOMErrorCodes, createDOMCompilerError } from '@vue/compiler-dom'
2import type { DirectiveTransform } from '../transform'
3import { IRNodeTypes } from '../ir'
4
5export const transformVShow: DirectiveTransform = (dir, node, context) => {
6 const { exp, loc } = dir
7 if (!exp) {
8 context.options.onError(
9 createDOMCompilerError(DOMErrorCodes.X_V_SHOW_NO_EXPRESSION, loc),
10 )
11 }
12
13 context.registerOperation({
14 type: IRNodeTypes.WITH_DIRECTIVE,
15 element: context.reference(),
16 dir,
17 name: 'vShow',
18 builtin: true,
19 })
20}
It's just registering WITH_DIRECTIVE
with name: 'vShow'
.
Reading the Runtime
This is also simple, so I'll include the entire text.
It simply sets el.style.display
to none
or ""
in beforeMount
, updated
, and beforeUnmount
.
1import type { ObjectDirective } from '../directives'
2
3const vShowMap = new WeakMap<HTMLElement, string>()
4
5export const vShow: ObjectDirective<HTMLElement> = {
6 beforeMount(node, { value }) {
7 vShowMap.set(node, node.style.display === 'none' ? '' : node.style.display)
8 setDisplay(node, value)
9 },
10
11 updated(node, { value, oldValue }) {
12 if (!value === !oldValue) return
13 setDisplay(node, value)
14 },
15
16 beforeUnmount(node, { value }) {
17 setDisplay(node, value)
18 },
19}
20
21function setDisplay(el: HTMLElement, value: unknown): void {
22 el.style.display = value ? vShowMap.get(el)! : 'none'
23}
And that's everything!