I am having problems with my Nuxt.js site.
I have defined a page, with a dynamic slug param, like this:
/solutions/:slug
If I visit the page directly in the browser, it loads correctly!
But if I click the nuxt-link in my NavBar component, I get the following error in the console, and the page does not load:
vue.runtime.esm.js?2b0e:619
[Vue warn]: Failed to mount component: template or render function not defined.
found in
---> <Anonymous>
<Nuxt>
<Layouts/default.vue> at layouts/default.vue
<Root>
I have a default layout file that looks like this:
layouts/default.vue
<template>
<div>
<NavBar />
<Nuxt />
</div>
</template>
<script>
import NavBar from "~/components/Layout/NavBar"
export default {
components: {
NavBar,
},
}
</script>
My navbar contains the following nuxt-link:
components/Layout/NavBar.vue
<template>
<b-navbar wrapper-class="container" fixed-top>
<template slot="end">
<nuxt-link
:to="{
name: 'solutions-slug',
params: { slug: 'performance' },
}"
class="navbar-item"
target="self"
>
<span class="icon is-medium">
<i class="ic ic--larger ic-b1-graph-bars-chart-rise" />
</span>
<span class="label">
Performance
</span>
</nuxt-link>
</template>
</b-navbar>
</template>
I have a page, defined by the slug param:
pages/solutions/_slug.vue
<template>
<div class="solution">
This is my solution page.
</div>
</template>
I am trying to understand why clicking the nuxt-link fails to load the page, even though I see the URL change in the browser correctly.
Thanks
After version v2.13, Nuxt can auto-import your components when used in your templates.
check the nuxt.config.js if components attribute is true then you don't need to import your component on the .vue files.
in your layouts/default.vue remove script tag ;-)
<template>
<div>
<NavBar />
<Nuxt />
</div>
</template>
If you need to categorize your components by folder, do the following.
goto nuxt.config.js and change your components attribute
export default {
components: {
dirs: [
'~/components',
{
path : '~/components/site/',
prefix: 'Site'
},
{
path : '~/components/admin',
prefix: 'Admin'
},
{
path : '~/components/admin/sub',
prefix: 'AdminSub'
}
]
}
}
for example, we have these components :
components
| site
- header
| admin
- header
- footer
| sub
- header
- footer
when we need to call components just separate prefixes and component names with a dash or write camelcase.
in your layouts/default.vue remove script tag ;-)
<template>
<div>
<!-- with dash -->
<site-header></site-header>
<admin-header></admin-header>
<admin-sub-header></admin-sub-header>
<!-- cammel -->
<SiteHeader></SiteHeader>
<AdminHeader></AdminHeader>
<AdminSubHeader></AdminSubHeader>
</div>
</template>
Attention: For Root Components /components/nav.vue, We Must Use CammelCase <Nav/> and if we call this component like this <nav/> it doesn't work.
Probably the problem is not related to anything described above.
First, check if your configuration is correct. I see you are using 'nuxtjs/content' module, so you are probably using Contentful as well. In the past, I have encountered a similar situation ('Failed to mount component: template or render function not defined' issue) due to incorrect installation of the 'dotenv' module that I used to store variables.
In my case, the application did not load variables from the .env file. As a consequence, they went to the Contentful client unidentified and caused the js error. For some reason, this error did not always appear in the console. Instead, the above-mentioned Warn appeared.
Make sure you have the 'dotenv' module correctly installed (if you use it). I remember that in my case it was necessary to install 'nuxtjs/dotenv' instead of the usual dotenv.
Let me know if this is the case. Good luck
Related
I have 2 components, AboutView.vue and HomeView.vue.
AboutView.vue
<template>
<div class="about">
<h1>This is an about page</h1>
<router-link to="/about/add">Add</router-link>
<router-view></router-view>
</div>
</template>
HomeView.vue
<template>
<div class="home">
<img alt="Vue logo" src="../assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
When I click the 'Add' button, I will be redirected to /about/add where /add is config inside index.js
{
path: '/about',
name: 'about',
component: AboutView,
children:[
{
path: 'add',
name: 'Add',
component: ()=> import ('../views/HomeView.vue'),
},
]
}
The path is working fine.
But the problem is when I click the 'Add' button, what I would expect is it brought me to the HomeView.vue, but instead, it showed the HomeView.vue below the Add button.
Here is the screen.
ScreenShot
it seems like the route-view is a part of the template, but I want it to display the HomeView.vue instead of AboutView + HomeView.
I tried to use <router-view name='name></router-view>, which doesn't help much. I can write a js function to check the path and make the code above disappear, but I expect something more professional.
Let's try to understand from the below image-
router-view is basically the view where the components are rendered.
It’s like the main div that contains all the components, and it
returns the component that matches the current route.
So, to fix this just remove the router-view from AboutView.vue component, so when you will redirect to /home, the component HomeView.vue, will render inside App.vue's router-view.
i'm new of this framework :(
the problem is here because i've tried to put the component in another page and work it.
It sign error the component
this is my index.vue page
If you're using nuxt2.0, you should wrap them in a container but this is not needed in nuxt3.0.
<template>
<main>
<navbar />
<slideshow />
</main>
</template>
If this is nuxt2.0, then you should also import the component and register it but you haven't done it here. The path you've given to the component is not correct also.
<script>
import Slideshow from '~/components/slideshow.vue';
export default {
components: { Slideshow }
}
</script>
You need to wrap the into a div or any other tag (to not have multiple tags at the root of the template) like that
<template>
<div>
<navbar></navbar>
<slideshow></slideshow>
</div>
</template>
And you can also skip the import part because Nuxt is already doing that for you as explained here: https://nuxtjs.org/tutorials/improve-your-developer-experience-with-nuxt-components/
My content folder has one directory called planets, which contains yaml files of different planets.
I want to render the planet pages as navigation items content navigation component
Currently i only get a link to the /planets page, so Im figuring that the component is reading the root content directory but I need to give it the /planets to read that instead.
In my index.vue file I have written this as per docs:
<nav>
<ContentNavigation v-slot="{ navigation }" :query="queryPlanets" >
<div v-for="link of navigation" :key="link._path">
<NuxtLink :to="link._path">{{ link.title }}</NuxtLink>
</div>
</ContentNavigation>
</nav>
<script setup>
const queryPlanets = queryContent('planets')
</script>
But I keep getting this vue router warn error:
[Vue Router warn]: No match found for location with path "/planets"
I have tried using the following:
const query = queryContent({
where: {
_path: { $contains: '/planets' }
}
})
Gives same error,
I have also tried to track the files down manually
const query = await useAsyncData('planets', () => queryContent('/planets').find('/'));
And I do find the files with the right paths and all the values.
So I believe this is some sort of vue router error, but
I am unsure how to debug this exactly.
I am using Nuxt3
Turns out when calling <ContentNavigation v-slot="{ navigation }" > you get everything including contents of nested directories.
So the navigation returns an object and then I can just write them out as follows:
<div v-for="dir in navigation" :key="dir._path" >
<div v-for="link in dir.children" :key="link._path">
<NuxtLink :to="link._path">
{{ link.title }}
</NuxtLink>
</div>
</div>
I have a very simple app vue3:
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
let currentApp = createApp(App);
(window as any).load(currentApp);
currentApp.mount('#app');
In the index.html file i import a dist lib:
<script src="http://localhost:5173/dist/assets/index.59eda240.js">
The content of dist JS is:
import HelloWorld from './components/HelloWorld.vue'
(window as any).load = (app: any) => {
app.component('hello-world', HelloWorld);
}
If i use a very simple HelloWorld.vue with just one line of text "Hello", all works fine, but if i put some css classes or more complicated component i obtain:
[Vue warn]: Invalid VNode type: Symbol() (symbol) at <HelloWorld>
at <App>
How can i solve this? Or is there another way to load component at runtime?
Thanks in advance.
P.s. I have no problem doing the same thing with Vue
--------- UPDATE MORE INFO ----------
Vue version
3.2.38
Link to minimal reproduction
https://stackblitz.com/edit/vitejs-vite-744fbh?file=src/main.js
Steps to reproduce
The base idea is to have a main app the create a Vue app, and another external lib the load component at runtime.
Open the sample project and show console log to see "Invalid VNode type: Symbol() (symbol)"
What is expected?
I expect to see the components rendered correctly
What is actually happening?
I don't see the component UI, but looking at the console I see the logic code works correctly but we have a warning: Invalid VNode type: Symbol() (symbol) Invalid VNode type: Symbol() (symbol)
System Info
No response
Any additional comments?
This warning appears only in some components, for example, fur a very simple component, it works fine, see here: https://stackblitz.com/edit/vitejs-vite-nueucw?file=src/App.vue.
You can see the source of helloworld component at the top of lib.js file, inside a comment block
The actual problem is that there are multiple Vue library copies per page that interact with each other. This should be avoided, preferably by bundling multiple parts of the application together, so multiple apps would reuse the same modules from vendors chunk. In case this isn't possible or practical, a simple workaround is to use Vue CDN for all applications, either by using window.Vue instead of vue import, or aliasing the import to global variable by means of a bundler.
The root cause is that Vue built-in element are specific to Vue copy in use - Fragment, Teleport, Comment, etc. They are defined with Symbol() to be distinguished from other elements and components and used in compiled component templates. Symbol is used in JavaScript to define unique tokens, Symbol('foo') !== Symbol('foo'). The symbols of built-in elements from one Vue copy mean nothing to another Vue copy, this is the meaning of this error message.
It can be seen in this analyzer that this component template:
<h1 style="background-color:Red; font-size: 44px;">{{ msg }}</h1>
<button #click="msg = 'click';">CLICK</button>
is compiled to this render function:
export function render(_ctx, _cache, $props, $setup, $data, $options) {
return (_openBlock(), _createElementBlock(_Fragment, null, [
_createElementVNode("h1", { style: {"background-color":"Red","font-size":"44px"} }, _toDisplayString(_ctx.msg), 1 /* TEXT */),
_createElementVNode("button", {
onClick: $event => {_ctx.msg = 'click';}
}, "CLICK", 8 /* PROPS */, ["onClick"])
], 64 /* STABLE_FRAGMENT */))
}
Notice that the use of multiple root elements results in wrapping them in Fragment, which won't be correctly processed by multiple Vue copies, etc.
Change hello world with another component:
<template>
<div class="relative flex items-top justify-center min-h-screen sm:items-center py-4 sm:pt-0">
<div class="max-w-6xl mx-auto sm:px-6 lg:px-8">
<div class="card rounded-lg shadow-lg" style="background-color: yellow;">
<div class="card-body p-0 m-0 pt-2" style="background-color: orange;">
<div class="row border-bottom p-0 m-0 pt-2" style="background-color: brown;">
<div class="bg-secondary">
<h5 class="bg-info">test</h5>
<p>
test
</p>
</div>
</div>
<div>
<div>
test2
</div>
</div>
</div>
</div>
</div>
</div>
</template>
Only one root element, I have the same issue.
Versions
nuxt: ^2.14.12
node: v14.15.4
Reproduction
Hello everyone and thank you in advance.
I have a strange issue that I don't really understand what's the problem and how to deal with it.
I have installed a fresh nuxt ssr project.
I'm getting the following warning
[Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content. This is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>, or missing <tbody>. Bailing hydration and performing full client-side render.
I have three simple components: Form, Input, Button.
Form.vue
<template>
<form v-bind="$attrs" class="w-full" #submit.prevent="$emit('submitted')">
<div class="space-y-2 mb-4">
<slot name="fields" />
</div>
<slot name="button" />
</div>
</form>
</template>
<script>
export default {
computed: {
hasFields() {
return !!this.$slots.fields
},
},
}
</script>
Input.vue
<template>
<div class="relative w-full">
<input class="form-input block w-full" />
</div>
</template>
<script>
export default {
inheritAttrs: false,
}
</script>
Button.vue
<template>
<button
type="submit"
class="relative btn inline-flex items-center justify-center transition ease-in-out duration-150"
>
Save
</button>
</template>
<script>
export default {}
</script>
I use my components in pages/index.vue like this:
<template>
<div>
<Form>
<template #fields>
<Input />
<Input />
</template>
<template #button>
<Button />
</template>
</Form>
<Form>
<template #fields>
<Input />
<Input />
</template>
<template #button>
<Button />
</template>
</Form>
</div>
</template>
<script>
export default {}
</script>
If i use the Form component only once in the view i don't get the warning.
If i use it twice i get it.
Steps to reproduce
Reproduction link
Install a fresh nuxt ssr project.
Create the components as in the reproduction link
What is Expected?
All the components to render normally without any warnings or errors.
What is actually happening?
I get the following warning.
[Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content. This is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>, or missing <tbody>. Bailing hydration and performing full client-side render.
Some extra notes
I know that wrapping the whole thing inside a <client-only> fixes the problem but i want to understand why is this happening in order to avoid it in future cases.
Also if I remove components: true from nuxt.config.js and import the components normally again the warning is gone.
Changing the name of the components eg Button -> TheButton won't fix the problem. You can see the reproduction here.
<script>
import Input from '~/components/Input'
import Button from '~/components/Button'
import Form from '~/components/Form'
export default {
components: { Form, Button, Input}
}
</script>
There seems to be one or more components which are not supported in "Universal" Mode, i.e. they might have code which isn't being executed correctly on server end.
Please try finding that component which you think can cause an issue and wrap that component with .
Here's the link for more information: https://nuxtjs.org/docs/2.x/features/nuxt-components#the-client-only-component