v-text ディレクティブ
以下のようなコンポーネントを考えます.
vue
<script setup>
import { ref } from "vue";
const message = ref("Hello, v-text!");
</script>
<template>
<p v-text="message" />
</template>
コンパイル結果と概要
コンパイル結果は以下のようになります.
js
const _sfc_main = {
vapor: true,
__name: "App",
setup(__props, { expose: __expose }) {
__expose();
const message = ref("Hello, v-text!");
const __returned__ = { message, ref };
Object.defineProperty(__returned__, "__isScriptSetup", {
enumerable: false,
value: true,
});
return __returned__;
},
};
import {
renderEffect as _renderEffect,
setText as _setText,
template as _template,
} from "vue/vapor";
const t0 = _template("<p></p>");
function _sfc_render(_ctx) {
const n0 = t0();
_renderEffect(() => _setText(n0, _ctx.message));
return n0;
}
v-text
を指定した要素が renderEffect
と setText
によって構築されるようになりました.
コンパイラを読む
transformElement
-> buildProps
-> transformProps
-> directiveTransform
-> transformVText
と辿っていきます.
非常にシンプルなので全文載せてしまいます.
1import { DOMErrorCodes, createDOMCompilerError } from '@vue/compiler-dom'
2import { IRNodeTypes } from '../ir'
3import { EMPTY_EXPRESSION } from './utils'
4import type { DirectiveTransform } from '../transform'
5import { getLiteralExpressionValue } from '../utils'
6
7export const transformVText: DirectiveTransform = (dir, node, context) => {
8 let { exp, loc } = dir
9 if (!exp) {
10 context.options.onError(
11 createDOMCompilerError(DOMErrorCodes.X_V_TEXT_NO_EXPRESSION, loc),
12 )
13 exp = EMPTY_EXPRESSION
14 }
15 if (node.children.length) {
16 context.options.onError(
17 createDOMCompilerError(DOMErrorCodes.X_V_TEXT_WITH_CHILDREN, loc),
18 )
19 context.childrenTemplate.length = 0
20 }
21
22 const literal = getLiteralExpressionValue(exp)
23 if (literal != null) {
24 context.childrenTemplate = [String(literal)]
25 } else {
26 context.registerEffect([exp], {
27 type: IRNodeTypes.SET_TEXT,
28 element: context.reference(),
29 values: [exp],
30 })
31 }
32}
registerEffect
しているだけです.transformText
の時と似たような処理を行っています.
ランタイムは特に読むところがないので今回もこれでおしまいです. サクサクいきましょう!