VueJS 3 routing with vue-router and CDN - vuejs2

For the past three hours or so, I have been trying to convert a VueJS 2 + vue-router + CDN project to VueJS 3. I haven't been able to make it work so far. The VueJS 2 version works just fine. The VueJS 3 version just won't work. I understand that sooner or later a project would need to be implemented with CLI, but I'd rather use CDN for the moment since I'm still experimenting.
The error message I receive is: Uncaught ReferenceError: createRouter is not defined. I have received many others in my trials and tribulations.
Here is the JS part (VueJS 2, works fine):
const Home = { template: `<h1>Contenuto Home</h1>` };
const About = { template: `<h1>Contenuto About</h1>` };
const Portfolio = { template: `<h1>Contenuto Portfolio</h1>` };
const Contatti = { template: `<h1>Contenuto Contatti</h1>` };
const routes = [
{ path: "/", component: Home },
{ path: "/about", component: About },
{ path: "/portfolio", component: Portfolio },
{ path: "/contatti", component: Contatti }
];
const router = new VueRouter({
routes // short for `routes: routes`
});
const vm = new Vue ({
router,
el: "#app",
data: {
mess: "Ciao Mondo"
}
}).$mount("#app");
The HTML looks like this (VueJS 2, works fine):
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue Router</title>
</head>
<body>
<div id="app">
<h1>{{ mess }}</h1>
<!-- i links -->
<router-link to="/">Home</router-link>
<router-link to="/about">About</router-link>
<router-link to="/portfolio">Portfolio</router-link>
<router-link to="/contatti">Contatti</router-link>
<!-- contenitore per il HTML -->
<router-view></router-view>
</div>
<!-- VueJS -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- vue-router -->
<script src="https://unpkg.com/vue-router#3.0.2/dist/vue-router.js"></script>
<!-- custom JS -->
<script src="main.js"></script>
</body>
</html>
Here is my attempt at converting this code to VueJS 3 (doesn't work - Uncaught ReferenceError: createRouter is not defined):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="https://unpkg.com/vue#next"></script>
<script src="https://unpkg.com/vue-router#4"></script>
<div id="app">
<h1>{{ mess }}</h1>
<!-- i links -->
<router-link to="/">Home</router-link>
<router-link to="/about">About</router-link>
<router-link to="/portfolio">Portfolio</router-link>
<router-link to="/contatti">Contatti</router-link>
<!-- contenitore per il HTML -->
<router-view></router-view>
</div>
<script>
let app = Vue.createApp({
data() {
return {
mess: "ciao mondo"
}
}
});
const Home = { template: `<h1>Contenuto Home</h1>` };
const About = { template: `<h1>Contenuto About</h1>` };
const Portfolio = { template: `<h1>Contenuto Portfolio</h1>` };
const Contatti = { template: `<h1>Contenuto Contatti</h1>` };
const routes = [
{ path: "/", component: Home },
{ path: "/about", component: About },
{ path: "/portfolio", component: Portfolio },
{ path: "/contatti", component: Contatti }
];
const router = new createRouter({
history: createWebHistory(process.env.BASE_URL),
routes // short for `routes: routes`
});
app.mount("#app");
</script>
</body>
</html>

const app = Vue.createApp({
data() {
return {
mess: "ciao mondo"
}
}
});
const Home = { template: `<h1>Contenuto Home</h1>` };
const About = { template: `<h1>Contenuto About</h1>` };
const Portfolio = { template: `<h1>Contenuto Portfolio</h1>` };
const Contatti = { template: `<h1>Contenuto Contatti</h1>` };
const routes = [
{ path: "/", component: Home },
{ path: "/about", component: About },
{ path: "/portfolio", component: Portfolio },
{ path: "/contatti", component: Contatti }
];
const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(),
routes
})
app.use(router)
app.mount('#app')

Related

Using vue-router with vuejs3 and I get this Vue warn: Component is missing template or render function

I'am trying to make a simply router with vue-router on vuejs3 and i get this warning on the first click on a link (not the others clicks):
vue#next:1571 [Vue warn]: Component is missing template or render function.
I use vuejs3, vue-router, vscode, chrome on ubuntu
My code :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Warn - Vue 3 / Router</title>
</head>
<body>
<div id="app">
<router-link to="/">Home</router-link>
<br />
<router-link to="/contact">Contact</router-link>
<router-view></router-view>
</div>
<script src="https://unpkg.com/vue#next"></script>
<script src="https://unpkg.com/vue-router#4.0.5/dist/vue-router.global.js"></script>
<script>
// App
const app = Vue.createApp({});
// Component
const Home = app.component("home", {
template: `<h1>Home</h1>`,
name: "Home",
});
const Contact = app.component("contact", {
template: `<h1>Contact</h1>`,
name: "Contact",
});
// Router
const router = VueRouter.createRouter({
history: VueRouter.createWebHistory(),
routes: [
{ path: "/", component: Home },
{ path: "/contact", component: Contact },
],
});
app.use(router);
app.mount("#app");
</script>
</body>
</html>
Can you correct or give me a link for implement vue-router on vuejs3 (i'm beginner on vuejs) ? Thanks
There are two problem:
The components is registered incorrectly
app.component("home", {
template: `<h1>Home</h1>`,
name: "Home",
});
const Home = app.component("home");
See: https://v3.vuejs.org/api/application-api.html#component
If you use Vue Router in HTML files, only use Hash Mode
- history: VueRouter.createWebHistory(),
+ history: VueRouter.createWebHashHistory(),
The full code is as follows:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Warn - Vue 3 / Router</title>
</head>
<body>
<div id="app">
<router-link to="/">Home</router-link>
<br />
<router-link to="/contact">Contact</router-link>
<router-view></router-view>
</div>
<script src="https://unpkg.com/vue#next"></script>
<script src="https://unpkg.com/vue-router#4.0.5/dist/vue-router.global.js"></script>
<script>
// App
const app = Vue.createApp({});
// Component
app.component("home", {
template: `<h1>Home</h1>`,
name: "Home",
});
const Home = app.component("home");
app.component("contact", {
template: `<h1>Contact</h1>`,
name: "Contact",
});
const Contact = app.component('contact')
// Router
const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(),
routes: [
{ path: "/", component: Home },
{ path: "/contact", component: Contact },
],
});
app.use(router);
app.mount("#app");
</script>
</body>
</html>

[Vue warn]: Failed to mount component: template or render function not defined, using Laravel 8

I'm trying to create a new project but I'm getting this error and I don't know why. I'm using Laravel 8, Vue and Inertia.js.
I'm not sure if these files are important but I'll add anyways
webpack.mix.js
const mix = require('laravel-mix');
const path = require('path');
mix.js('resources/js/app.js', 'public/js').vue({ version: 2 })
.sass('resources/sass/app.scss', 'public/css')
.webpackConfig({
output: { chunkFilename: 'js/[name].js?id=[chunkhash]' },
resolve: {
alias: {
vue$: 'vue/dist/vue.runtime.esm.js',
'#': path.resolve('resources/js'),
},
},
})
.babelConfig({
plugins: ['#babel/plugin-syntax-dynamic-import'],
})
.version();
app.js
import InertiaApp from '#inertiajs/inertia-vue'
import Vue from 'vue'
Vue.use(InertiaApp);
const app = document.getElementById('app');
app.setAttribute(':class',"{'loaded': loaded}");
new Vue({
render: h => h(InertiaApp, {
props: {
initialPage: JSON.parse(app.dataset.page),
resolveComponent: name => import(`#/Pages/${name}`).then(module => module.default),
},
data(){
return{
loaded:true
}
}
}),
}).$mount(app);
app.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<!-- Scripts -->
<script src="{{ asset('js/app.js') }}" defer></script>
<!-- Styles -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
#inertia
</body>
</html>
Finally the page I'm trying to show Login.vue
<template>
<div>
<h1>Login</h1>
</div>
</template>
<script>
export default {
data() {
return {}
},
mounted() {
console.log('mounted');
}
}
</script>
I don't know why this is happening or how to fix it.
What am I doing wrong?

How to use vue-router-next without bundler?

The previous version of vue-router uses the global application instance and mounts the plugin automatically:
if (inBrowser && window.Vue) {
window.Vue.use(VueRouter);
}
Now this possibility was restricted in Vue 3 version. So, how I should get VueRouter to pass to app.use(VueRouter) if I use CDN instead of bundler in vue-router-next?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script src="https://unpkg.com/vue#next"></script>
<script src="https://unpkg.com/vue-router#next"></script>
<div id="app">
<ul>
<li><router-link to="/">Home</router-link></li>
<li><router-link to="/foo">Foo</router-link></li>
<li><router-link to="/bar">Bar</router-link></li>
</ul>
<router-view></router-view>
</div>
<script>
const { createRouter, createWebHistory, createWebHashHistory } = VueRouter
const { createApp } = Vue
const Home = {
template: `<div>home</div>`,
}
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/', component: Home },
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar },
],
})
const app = createApp({})
app.use(router)
window.vm = app.mount('#app')
</script>
</body>
</html>
Credits to posva

Does vue-router works with inline-templates?

I'm trying to render multiple components that use inline-templates using vue-router but as soon as i define the inline-template the component renders no matter the url.
Does inline-templatesworks with vue-router?
It really depends on what you mean by "work". You can Frankenstein something like this and it will do what you want without throwing any errors, but I feel I'm making the world an uglier place by just posting this example:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Vue-router with inline-template</title>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
<div id="app">
<router-link to="/foo">Go to Foo</router-link>
<router-link to="/bar">Go to Bar</router-link>
<router-view>
<foo inline-template id="foo"><div>foo</div></foo>
</router-view>
</div>
<script>
const Foo = { template: document.getElementById('foo').innerHTML };
const Bar = { template: '<div>bar</div>' };
const routes = [
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar },
];
const router = new VueRouter({
routes,
});
var app = new Vue({
el: '#app',
router,
});
</script>
</body>
</html>
This is pretty much the intro example from vuejs.org with one of the templates made into inline.
You can refer to your inline template using #
const Foo = { template: '#my-foo-template' }
const routes = [
{ path: '/foo', component: Foo },
];
<foo inline-template id="my-foo-template"> ... </foo>

Vue.js vue-router issue using navigation guard

I am trying to use a navigation guard w my router... when I use it the App component is displayed ( the navigation header) but the child HomePage component is not displayed... If I get rid of the navigation guard, no problem App and HomePage components are well displayed
what's wrong with my navigation guard usage in this case ?
router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import Home from '#/pages/HomePage'
import ShoppingLists from '#/pages/ShoppingListsPage'
Vue.use(Router)
const router = new Router({
// HTML5 mode history
mode: 'history',
routes: [
{
path: '/',
name: 'Home',
component: Home,
meta: { title: 'Home' }
},
{
path: '/shoppinglists',
name: 'ShoppingLists',
component: ShoppingLists,
meta: { title: 'Shopping Lists' }
}
]
})
router.beforeEach(function (to, from, next) {
if (to.meta && to.meta.title) {
document.title = to.meta.title
}
})
export default router
main.js
import Vue from 'vue'
import App from './App'
import router from './router'
/* eslint-disable no-new */
new Vue({
el: 'app',
router,
components: { App }
})
App.vue
<template>
<div id="app">
<ul class="navigation">
<li id="home"><router-link :to="{ name: 'Home' }" >Home</router-link></li>
<li id="shoppinglists"><router-link :to="{ name: 'ShoppingLists' }" >Shopping Lists</router-link></li>
</ul>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'app'
}
</script>
HomePage.vue
<template>
<div class="hello">
<img src="./../assets/logo.png">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
name: 'Hello',
data () {
return {
msg: 'Welcome to our ShoppingList app'
}
}
}
</script>
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>shopping-list</title>
<link rel="shortcut icon" type="image/png" href="/static/favicon.ico"/>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<app></app>
<!-- built files will be auto injected -->
</body>
</html>
You have forgotten to add next().
router.beforeEach(function (to, from, next) {
if (to.meta && to.meta.title) {
document.title = to.meta.title
next()
}
next()
})