Use "@vue/compiler-sfc" to get a root component, but the _ctx of render function doesn't have any my variable and throw a reading undefined error.
Vue version
3.3.4
Link to minimal reproduction
Steps to reproduce
- create a sfc file and write
input
,v-model="form.a"
andconst form = reactive({a:"str"})
with the setup mode. it as a root app component. - use "@vue/compiler-sfc" to get a js file of the app component.
- add the render function to compileScript functions 's output, such as
let __component: DefineComponent; // it is compileScript() 's output.
function render(_ctx, _cache){/*...*/} // it is compileTemplate() 's output.
__component.render = render
createApp(__component).mount("#app");
- got the "Cannot read properties of undefined".
What is expected?
Render a <input /> with v-model.
What is actually happening?
Cannot read properties of undefined (reading 'value').
object _ctx
of render(_ctx)
does not has the form
reactive.
System Info
System:
OS: Windows 10 10.0.22621
CPU: (32) x64 13th Gen Intel(R) Core(TM) i9-13900HX
Memory: 14.55 GB / 31.74 GB
Binaries:
Node: 20.3.1 - D:\Program Files\nodejs\node.EXE
Yarn: 1.22.19 - ~\AppData\Roaming\npm\yarn.CMD
npm: 9.6.6 - D:\Program Files\nodejs\npm.CMD
pnpm: 8.6.7 - ~\AppData\Roaming\npm\pnpm.CMD
Browsers:
Edge: Spartan (44.22621.2134.0), Chromium (115.0.1901.203)
Internet Explorer: 11.0.22621.1
Any additional comments?
Use koa, @vue/compiler-sfc and babel, but do not include the Vite. Vite was too heavy, so instead of using it, I made my own loader using KoaController, @vue/compiler-sfc and babel.
Compile SFC file at run time, but all the browser receives is "text/javascrtpt".
There is a simplified version in SFC Playground
SFC code:
<template>
<div>
<input v-model="form.value" type="text" />
</div>
</template>
<script lang="ts" setup>
import { reactive } from 'vue';
const form = reactive({
value: 'str',
});
</script>
<style scoped lang="scss">
input {
background-color: blue;
}
</style>
Full raw es6 javascript code in a html file:
import { vModelText as _vModelText, createElementVNode as _createElementVNode, withDirectives as _withDirectives, openBlock as _openBlock, createElementBlock as _createElementBlock } from "/oAuth/lib/vue";
import { defineComponent as _defineComponent } from "/oAuth/lib/vue";
import { reactive } from "/oAuth/lib/vue";
const __component = _defineComponent({
setup(__props, {
expose: __expose
}) {
__expose();
const form = reactive({
value: 'str'
});
const __returned__ = {
form
};
Object.defineProperty(__returned__, '__isScriptSetup', {
enumerable: false,
value: true
});
return __returned__;
}
});
export function render(_ctx, _cache) {
return _openBlock(), _createElementBlock("div", null, [_withDirectives(_createElementVNode("input", {
type: "text",
"onUpdate:modelValue": _cache[0] || (_cache[0] = $event => _ctx.form.value = $event)
}, null, 512), [[_vModelText, _ctx.form.value]])]);
}
__component.__scopeId = "data-v-sfc18";
__component.render = render;
const onAppCreate = () => {};
const onBeforeAppCreate = () => {};
__component.appCreate = c => import("/oAuth/lib/vue").then(it => it.createApp(c));
;
export let app = void 0;
(async () => {
let appCreate = __component.appCreate;
if (!appCreate) appCreate = () => import("/oAuth/lib/vue").then(it => it.createApp(c));
const app1 = await appCreate(__component);
app = app1;
app1.mount('#app');
})();
export default __component;
;
(url => {
const styles = `input[data-v-sfc18] {
background-color: blue;
}
`;
let dom = document.head.querySelector(`style[data-url="${url}"]`);
dom?.remove();
dom = document.createElement('style');
dom.setAttribute('data-url', url);
dom.innerHTML = styles;
document.head.append(dom);
})("/oAuth/test.a.vue");