use dynamic component in the nuxt layout get runtime compile error - vue.js

in my nuxt application. in layout file use dynamic component for set the component in different pages like below
<template>
<div id="app">
<div id="app-body">
<div id="app-topbar">
<component v-bind:is="actionBar.component"></component>
</div>
<div id="app-content">
<nuxt />
</div>
</div>
</div>
</template>
but when I'm runing the application I got the error in below
You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
I'll try to wrap my component in no-ssr tags but the error still exist

as DigitalDrifter already said, you need to use the compiler-included build.
To do that in nuxt try to add the following to your nuxt.config.js:
build: {
extend(config, ctx) {
config.resolve.alias['vue'] = 'vue/dist/vue.common'

Related

Inject Vue component from diet js file

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.

How do I use slots from a Vue2 webcomponent in Vue3?

The component I am trying to use is written in Vue2 and is installed through NPM as a webcomponent. My new project is created in Vue3.
I'm trying to use a components slots, but it's not working.
When I try the following I get no errors, but nothing is rendered inside the slots of the webcomponent:
<my-webcomponent-with-two-slots>
<main>
<div>Hello World</div>
</main>
<sidebar>
<div>Hello World</div>
</sidebar>
</my-webcomponent-with-two-slots>
When I try the following I get an error: error 'slot' attributes are deprecated vue/no-deprecated-slot-attribute
<my-webcomponent-with-two-slots>
<div slot="main">
<div>Hello World</div>
</div>
<div slot="sidebar">
<div>Hello World</div>
</div>
</my-webcomponent-with-two-slots>
I cannot change or upgrade the webcomponent I want to use. How do I use it in my Vue3 project?
EDIT: I should clarify that the webcomponent is working using an older project written in Vue2, using the second example.
Vue is complaining about the older slot attribute that has been changed to v-slot. But you're not using vue slots, you're using WebComponent's native slot attribute. So you can safely disable this check in your .eslintrc.js file by adding
rules: {
'vue/no-deprecated-slot-attribute': 'off',
}
to your rules to globally disable this rule.
Or if you'd like to disable it for a single line, add this before the line:
<!-- eslint-disable-next-line vue/no-deprecated-slot-attribute -->
<div slot="main">
<div>Hello World</div>
</div>
<!-- eslint-disable-next-line vue/no-deprecated-slot-attribute -->
<div slot="sidebar">
<div>Hello World</div>
</div>

How do I do syntax highlighting in VueJS

How do I display syntax-highlighted HTML code like this picture from the VueJS documentation?
I have tried using v-html but I just get a console error.
Upon inspecting the VueJS documentation code snips, you can see they contain the class hljs.
This class is used by HighlightJS, a simple framework for code syntax highlighting.
HighlightJS automatically detects the language based on the syntax and can be extended with custom themes and configurations.
To install it in your vue package simply run either npm install highlight.js --save or yarn add highlight.js.
Once installed, import it and register it as a Vue plugin Vue.use(hljs.vuePlugin);
You can then use the component within your Vue templates:
<div id="app">
<!-- bind to a data property named `code` -->
<highlightjs autodetect :code="code" />
<!-- or literal code works as well -->
<highlightjs language='javascript' code="var x = 5;" />
</div>
You can find the above Vue example here in the documentation.
You could just put out the sanitized string:
new Vue({
el: "#app",
data() {
return {
script: `<script src="https://unpkg.com/vue#next"></script>`,
}
},
template: `
<div>
Code:<br>
<code v-html="script"></code><br>
</div>
`,
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>

Nuxt.js could not found component with errors "Failed to mount component: template or render function not defined."

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

Safari shows a component error while the other browsers do not

I have some very simple vue code as shown below:
Vue.component('tabs', {
template: `
<div class="">
<div class="tabs">
<ul>
<li><a>Music</a></li>
<li><a>Videos</a></li>
<li><a>Documents</a></li>
</ul>
</div>
<div class="tab-detail">
<slot></slot>
</div>
</div>
`
});
new Vue ({
el: '#root'
});
and HTML code
<div id="root" class="container">
<tabs>
</tabs>
</div>
the problem I have is that the safari throws a warning:
[Vue warn]: Unknown custom element: <tabs> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
(found in <Root>)
I am a Vue beginner so I was looking for the solution but the answer I got was that I should just declare the new Vue after the component. That I did but I am still getting this error.
This is because Safari does not support es6 template string syntax ``. In order to fix it you should use Webpack or just a Babel to add support for new es6 features.