I have been stuck on this issue for a while with no information online. using vue 3
I define a layout component inside my router meta: tag.
Inside my App.vue I check if a specified route has the layout meta tag, and if so the `component :is="layout" is true.
App.vue
<template>
<component :is="layout">
<router-view />
</component>
</template>
<script>
computed: {
layout() {
let layout = null;
for (const match of this.$route.matched)
if (match.meta && match.meta.layout) layout = match.meta.layout;
if (layout) return layout;
return "div";
},
}
</script>
router.vue
const usLayout = () => import("../layouts/usLayout.vue");
{
path: "/",
name: "us",
component: GenericRouterView,
meta: { layout: usLayout },
children: usRoutes,
},
I get this error:
[Vue warn]: Invalid VNode type: undefined (undefined) at UsLayout at App
And nothing is displayed on the screen. Any ideas what this error means / what causes it?
Your problem is that you are using div in is="div". The :is directive in component only accepts a component definition and not a tag.
With your code is not possible to have a direct render of the component as it is. You will have to wrap into another div or use render functions:
<template>
<div>
<template v-if="layout === 'div'">
<router-view />
<template>
<template v-else>
<component :is="layout">
<router-view />
</component>
</template>
</div>
</template>
<script>
computed: {
layout() {
let layout = null;
for (const match of this.$route.matched)
if (match.meta && match.meta.layout) layout = match.meta.layout;
if (layout) return layout;
return "div";
},
}
</script>
With render functions:
<script>
computed: {
layout() {
let layout = null;
for (const match of this.$route.matched)
if (match.meta && match.meta.layout) layout = match.meta.layout;
if (layout) return layout;
return "div";
},
render(createElement) {
return createElement(this.layout, [...])
}
}
</script>