I am using VueJS Router, but the router is not loading the components.
I have About.vue and Contact.vue just with tag to test - following is how it looks like :
<template>
<div>
<h1>Contact page. Welcome baby!</h1>
</div>
</template>
This is App.vue with three router-links and router-view.
<template>
<div>
<h1>Routing</h1>
<router-link to="/">Home</router-link>
<router-link to="/about">About</router-link>
<router-link to="/contact">Contact</router-link>
<router-view></router-view>
</div>
</template>
This is main.js (the paths of importing files are correct)
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
import {routers} from './router'
Vue.use(VueRouter);
let router = new VueRouter({mode: 'history', routers});
new Vue({
el:'#app',
router,
components: {
'app-home' : App
}
});
This is the JS file for the router. router.js (paths are correct)
import About from './About.vue'
import Contact from './Contact.vue'
import Home from './App.vue'
export const routers=[
{
path: '/' , component: Home
},
{
path:'/about',component:About
},
{
path:'/contact',component:Contact
}
]
And, this is index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>router</title>
</head>
<body>
<div id="app">
<app-home></app-home>
</div>
<script src="/dist/build.js"></script>
</body>
</html>
When I load the page, the main page looks like the following :
and when I click the each nav, nothing is changed from the main page except URL.
URL becomes
http://localhost:8080/contact
http://localhost:8080/about
but not loading the component I imported.
If you need more information to give advice, feel free to ask more.
And if you have any clue of this issue, I appreciate if you share here.
Thank you.
The object key VueRouter is expecting is called routes, you are passing it routers.
Try this...
let router = new VueRouter({mode: 'history', routes: routers});
Alternatively, rename your "routers" variables to "routes". Eg
export const routes=[
and
import {routes} from './router'
// snip
let router = new VueRouter({mode: 'history', routes });
In my case I had to create a new Vue project (vue create Project) with "Manually select features"; then I had to mark "Router".
Previously I've created a project with defaults and I've installed router separately (npm install vue-router) - but at the end the routing didn't load the components.
ps. I use:
npm 6.14.6
nodejs v12.18.3
#vue/cli 4.5.4
I was having the same symptoms as the OP but using netlify and gridsome (which uses vue.js. In my case it was a incorrectly tagged contact form that was the cause.
Related
So using router/index.js I managed to at least get the home page displayed. Now I have moved the code to main.js to simplify it for this question, and not even the home page loads. I only get the vue logo:
main.js:
import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import App from './App.vue'
import Home from '#/pages/Home.vue'
import DiscussionPage from '#/pages/DiscussionPage.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/discussion-page/:id',
name: 'DiscussionPage',
component: DiscussionPage,
props: true
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
const forumApp = createApp(App)
forumApp.use(router)
forumApp.mount('#app')
Here's the template from the homepage (Home.vue inside src/pages):
<template>
<div class="home">
<p>This is the home page</p>
<div class="discussions" v-for="discussion in discussions" :key="discussion.id">
<router-link :to="{name: 'DiscussionPage', params: {id: discussion.id}}">
{{ discussion.word}}
</router-link>
</div>
</div>
</template>
There was no issues getting the discussions data before I added vue-router, is why I am not including that part of the code. Also, before I moved the code to main.js the url would change when clicking the router-link for the discussion page, but the page would not load.
I am using vue-router4 and I built the app using the CLI with the default vue3 option.
Any clues of what it is I am doing wrong? I am sure it is anobvious little detail, but I can't find it :-(
Thank you so much :-)
This was really silly, but I guess it is still worth publishing for beginners?
For the vue-router to work, one must add the router-view tag. I guess I could have added it in my home page as Bulent suggested. But I think it makes more sense to add it in App.vue so that affects the whole app.
I have to say that this is not clear at all from the current documentation: https://next.router.vuejs.org/guide/#router-link
So simply adding this on App.vue activated the router, and all works well now :
<template>
<router-view/>
</template>
I have two sign up components that contain forms, one for those signing up as individuals and one signing up as businesses, I have a main page component with two large buttons labeled, "Click here to sign up as an individual", "Click here to sign up as a business'. How do I link these components on Vue? I am hoping that upon click of the button the component renders on the same page and not a new tab.
Thanks in advance!
So far,
Attempted to configure the router.js(I have a feeling this might be where my issue is)
Added the routes to the v-button
App.vue
<template>
<v-app>
<v-btn dark to="./components/CompanySignUp"> Sign up as a Company </v-btn>
<v-btn dark to="./components/FreelanceSignUp"> Sign up as a Freelancer
</v-btn>
</v-app>
</template>
<script>
export default {
name: "App",
components: {},
data: () => ({
//
})
};
</script>
router.js
import Vue from "vue";
import Router from "vue-router";
import CommpanySignUp from "./components/CompanySignUp";
import FreelancerSignUp from "./components/FreelancerSignUp";
Vue.use(Router);
const router = new Router({
mode: "history",
base: process.env.BASE_URL,
routes: [
{
path: "./components/CompanySignUp",
name: "Company Sign Up",
component: CommpanySignUp
},
{
path: "./components/FreelancerSignUp",
name: "Freelancer Sign Up",
component: FreelancerSignUp
}
]
});
main.js
import Vue from "vue";
import App from "./App.vue";
import vuetify from "./plugins/vuetify";
import 'material-design-icons-iconfont/dist/material-design-icons.css'
import VueRouter from "vue-router";
Vue.use(VueRouter);
Vue.config.productionTip = false;
new Vue({
vuetify,
render: h => h(App)
}).$mount("#app");
This sounds like a good opportunity to use vue-router, but there are multiple approaches to this problem. Depending on scope, there may be more than one good answer. There is a comment above about using emitters and props, which is fine, but I would recommend using vue-router because it's made for this kind of dynamic component switching. If you've used the vue-cli it should be trivial to add, but the following example uses the standalone CDNs for brevity. This can all be done in separate files and the vue-cli will already have a nice scaffold for you if you want to see how that's done.
const Main = {
template: `
<div>
<router-link to="/register/business">Register for business</router-link>
<router-link to="/register/personal">Register for personal</router-link>
</div>
`
};
const RegistrationPage = { template: '<router-view></router-view>' };
const BusinessRegistration = {
template: `
<h1>Business</h1>
`
};
const PersonalRegistration = {
template: `
<h1>Personal</h1>
`
};
const routes = [
{
path: '/',
component: Main
},
{
path: '/register',
component: RegistrationPage,
children: [
{
path: 'business',
component: BusinessRegistration
},
{
path: 'personal',
component: PersonalRegistration
}
]
}
];
const router = new VueRouter({
routes
});
const app = new Vue({
router
}).$mount('#app');
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="https://unpkg.com/vue-router#2.0.0/dist/vue-router.js"></script>
</head>
<body>
<div id="app">
<router-view></router-view>
</div>
</body>
</html>
There are multiple benefits to this approach:
Vue router is supported pretty well by the Vue community so you can find lots of documentation and examples.
Your end user can visit mysite.com/register/business and land on the correct page, rather than having to go through clicking on the button if they decide to leave your page and come back.
Much of the logic is abstracted away by the library rather than having to do complex conditional logic and event emitters.
This is a very simple example that relies heavily on the "getting started" docs here. If you did start your project with the vue-cli, you should be able to run vue add vue-router, which should do some setup for you if you missed that step in the project creation process, otherwise you can use npm and set things up manually.
Assuming that your vue router is already working and you already displayed your component What you did is already correct, just follow these steps to make it working.
First put a router view in your main app . like below
<v-app>
<v-btn dark to="./components/CompanySignUp"> Sign up as a Company </v-btn>
<v-btn dark to="./components/FreelanceSignUp"> Sign up as a Freelancer
</v-btn>
<router-view></router-view>
</v-app>
Second change your route name into this one, this route name will be use to call you component itself.
{
path: "./components/CompanySignUp",
name: "company_sign_up",
component: CommpanySignUp
},
Lastly in your main, the final structrue is like this
<v-app>
<v-btn dark to="{name:'company_sign_up'}"> Sign up as a Company </v-btn>
<v-btn dark to="{name:'freelancer_sign_up'}"> Sign up as a Freelancer
</v-btn>
<router-view></router-view>
</v-app>
You have your router.js file defined correctly but you never included it in your app. Instead, you initialized another (empty) router in main.js. Just import your router.js and then include it in your initialization of the app.
import router from 'router.js'; <--- your file
new Vue({
router, <--------- apply router
render: h => h(App)
}).$mount("#app");
The last thing left is to define a place for the router components to render. That is accomplished by placing a <router-view> compenent somewhere in your app template.
<template>
<v-app>
<v-btn dark to="./components/CompanySignUp"> Sign up as a Company </v-btn>
<v-btn dark to="./components/FreelanceSignUp"> Sign up as a Freelancer
</v-btn>
<router-view></router-view> <------------- component rendered here
</v-app>
</template>
For maintenance reasons, consider using the name parameter for the :to prop so you can minimize code changes if you ever need to update the path.
I am trying to get the simplest of page routing working using vue-cli.
I have been trying to follow the Vue-router documentation (https://router.vuejs.org/guide/#html) as well as various other guides I have come across on google and have not been successful getting anything working on vue-cli.
I was able to get the example shown here: https://www.tutorialspoint.com/vuejs/vuejs_routing working, which does not use vue-cli. From there I tried to 'copy' that example into vue-cli to see if I can get it to work.
My main.js file looks like this:
import Vue from 'vue';
import VueRouter from 'vue-router';
import App from './App.vue';
Vue.config.productionTip = false
const Route1 = { template: '<div>router 1</div>' }
const Route2 = { template: '<div>router 2</div>' }
const routes = [
{ path: '/route1', component: Route1 },
{ path: '/route2', component: Route2 }
];
const router = new VueRouter({
routes
});
new Vue({
el: '#app',
router,
render: h => h(App)
});
And my App.vue file looks like this:
<template>
<div id="app">
<h1>Routing Example</h1>
<p>
<router-link to = "/route1">Router Link 1</router-link>
<router-link to = "/route2">Router Link 2</router-link>
</p>
<router-view></router-view>
</div>
</template>
<script>
export default {
}
</script>
It does not work. I have tried both direct access to the dist/index.html on the file system and viewing the app on localhost, using npm run serve. I see the page but the <router-link> tags render only as <router-link>, not as anchor (<a>) tags. It is impossible to click on them and thus no routing is happening.
The page in my browser has the following source:
<!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">
<link rel="icon" href="favicon.ico">
<title>ucic</title>
<link href="js/app.a486cc75.js" rel="preload" as="script">
<link href="js/chunk-vendors.a6df83c5.js" rel="preload" as="script">
</head>
<body>
<noscript><strong>We're sorry but ucic doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript>
<div id="app">
<h1>Routing Example</h1>
<p>
<router-link to="/route1">Router Link 1</router-link>
<router-link to="/route2">Router Link 2</router-link>
</p>
<router-view></router-view>
</div>
<script src="js/chunk-vendors.a6df83c5.js"></script>
<script src="js/app.a486cc75.js"></script>
</body>
</html>
There are no console errors and no errors trying to download javascript files.
Can anyone point me in the right direction? What am I doing wrong?
Update:
As Pukwa has mentioned, I did not correctly mount the application. After doing so I no longer receive a white screen, but as mentioned above, the <router-link> tag is not rendering as an anchor but literally as a <router-link> tag. The javascript is obviously doing something, or else even that wouldn't show up on the page.
I've updated my question rather than ask a new one as my original problem has not been solved (vue-router is still not working) and this is only one of many iterations to try and get this to work (I have, on previous iterations, had the application correctly mounted and seen the error described above).
I guess you did not mount your application inside of main.js
new Vue({
el: '#app',
router,
render: h => h(App)
});
I had to apply three fixes to make this code work:
mounting the application as identified by Puwka in their answer
Adding Vue.use(VueRouter); in main.js (I got help from answers to this question: [Vue warn]: Unknown custom element: <router-view> - did you register the component correctly?)
Adding "runtimeCompiler": true to vue.config.js (I got help from answers to this question: Vue replaces HTML with comment when compiling with webpack and this: https://cli.vuejs.org/config/#runtimecompiler)
Additionally, I was not able to see logs in the console because it seems vue or npm turns off logging? (I have to use // eslint-disable-next-line no-console before I can use a console.log statement).
A comment to this question Vue router does not render/mount root path component helped me to resolve that problem. Somehow, after logging out this.$router.currentRoute.path in a mounted function I was able to see the errors in the developer console.
I have a really simple minimal example page with vue-router which is only partially working.
app.js
import 'babel-polyfill';
import Vue from 'vue';
import VueRouter from 'vue-router';
import App from './app.vue';
import router from './router'
new Vue({
router,
render: h => h(App)
}).$mount('#app')
app.vue
<template>
<div class="container">
<div id="nav">
<router-link to="/">Page 1</router-link>|
<router-link to="/page2">Page 2</router-link>
<router-link to="/sretbs">No page</router-link>
</div>
<div style="border:5px solid green">
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {};
</script>
router.js
import Vue from 'vue'
import Router from 'vue-router'
import Page1 from './page1.vue';
import Page2 from './page2.vue';
import ErrorPage from './error.vue';
Vue.use(Router)
export default new Router({
routes: [
{ path: '/page1', name: 'page1', component: Page1 },
{ path: '/page2', name: 'page2', component: Page2 },
{ path: '*', component: ErrorPage }
],
redirect: {
"/": "page1"
}
})
The <router-view> appear to work on first page load. It shows the component I expect for whatever route is currently in the url (e.g. localhost/test#/page2), or if I explicitly route.push before binding Vue to #app it also shows the expected component.
Navigating to other routes doesn't appear to fully work, or at least it's not rendering the new route. When I add debug output to the page components like so:
<template>
<div class="container">
<h2>this is page 2</h2>
<buttons></buttons>
</div>
</template>
<script>
export default {
beforeRouteEnter: function(to, from, next) {
console.log(`Entering page 2:`);
next();
},
beforeRouteLeave: function(to, from, next) {
console.log(`Leaving page 2`);
next();
},
beforeRouteUpdate: function() {
console.log(`Before route update`);
}
};
</script>
it is picking up the routeenter/leave events. I can seemingly navigate back and forth between routes, but you don't see the result until a page reload
I can't recreate the problem in a jsfiddle, and I've scrapped everything and started again but am getting the same result. I can't see anything I'm doing wrong from looking at the Vue Router documentation. Any idea what I'm missing here?
In this instance the answer was painfully simple. There was another Vue instance on the page elsewhere. Even though my understanding is separate Vue instances bound to different container elements should be able to exist in harmony, in this instance it wasn't. It was also what was breaking the Vue dev tools, showing a Vuex instance for example but not showing any of the loaded components and giving a Cannot read property '__VUE_DEVTOOLS_UID__' of undefined error in the Vue Dev Tools errors.
Trying set up Vue Router. Not sure what I am doing wrong. Getting the error
Failed to mount component: template or render function not defined. (found in root instance)
Again, I'm coming to Vue from React and while they are pretty similar there are small things that are different and there aren't as many Vue resources out there yet.
I'm using the Webpack template and using single file components. One thing I didn't completely understand was this part in the documentation
// 1. Define route components.
// These can be imported from other files
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }
Is this just he same as me doing import Foo from 'path/to/component/ ?
Anyway, thanks for any and all help!
Here is my main.js file
import Vue from 'vue'
import App from './App'
import QuizBuilder from '../src/components/QuizBuilder.vue'
import ResourceInfo from '../src/components/ResourceInfo.vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
{ path: '/info', component: ResourceInfo },
{ path: '/quiz-builder', component: QuizBuilder }
]
const router = new VueRouter({
routes
})
const app = new Vue({
router
}).$mount('#app')
My index.html looks like this
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<title>Digestible</title>
</head>
<body>
<div id="app">
<router-view></router-view>
</div>
<!-- built files will be auto injected -->
</body>
</html>
Assuming you have the components properly, you still need a small update.
When loading vue router as module system, the application should be initialized with the following way:
new Vue({
el: '#app',
router,
render: h => h(App)
});