vue-router not rendering new components on route change - vuejs2

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.

Related

vue-router: pages not loading

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>

Vue Router import not working with require

I'm setting up a brand new Vue 2 project. Due to compatibility issues with one of the libraries I need to use, I can't yet move to Vue 3.
I have a very basic setup at the moment, folder structure something like this:
/
App.vue
main.js
router.js
/pages
AboutUs.vue
Home.vue
If I don't use Vue Router, and just import the AboutUs page into App.vue and call its tag in the template, it displays as expected.
When I instead use the Vue Router to render it in the <router-view /> tag in App.vue, I get the error message:
[Vue warn]: Failed to mount component: template or render function not defined.
I suspect that means I'm doing something wrong in the router but I can't see what.
main.js
import Vue from 'vue'
import App from './App.vue'
import router from 'router.js'
new Vue({
render: h => h(App),
router
}).$mount('#app')
App.vue
<template>
<div id="app">
<router-link to="/">Home</router-link>
<router-link to="/About">About</router-link>
<router-view />
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
router.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const About = require('../pages/AboutUs')
const Home = require('../pages/Home')
const routes = [
{
path: '/about',
name: 'About',
component: About
},
{
path: '*',
name: 'Home',
component: Home
}
]
const router = new VueRouter({
linkExactActiveClass: '',
routes
})
export default router
About.vue
<template>
<div>
<h1>About</h1>
</div>
</template>
<script>
export default {
}
</script>
es6 import
Try to use an es6 import instead of require:
import About from '../pages/AboutUs'
import Home from '../pages/Home'
Then your route syntax will work as is. This is because when you use require, you get the whole module rather than the Component export from the module.
-or-
require
Alternatively, if you wanted to continue using require, you would need the following syntax, using the default property of the module:
const About = require('../pages/AboutUs')
const Home = require('../pages/Home')
const routes = [
{
path: '/about',
name: 'About',
component: About.default
},
{
path: '*',
name: 'Home',
component: Home.default
}
]

Router-Link calling in the url but not displaying the page always main showing

i am a newbie in vuejs. I wanted to display the other page when clicking the link in the main page. However i already put the router-link tag. but when running in dev and click the url is adding but the page is not redirecting. Kindly help me. Thank you.
index.js
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export const constantRouterMap = [{
path: '/main',
component: () =>
import ('../views/main/main'),
hidden: true
},
{
path: "/about",
component: () =>
import ('../views/about/about'),
}
]
export default new Router({
// mode: 'history',
routes: constantRouterMap
})
export const asyncRoutes = []
main.vue
<template>
<div id="main">
<router-link to="/about">
About
</router-link>
</div>
</template>
about.vue
<template>
<div class="about">
<h1>This is about page</h1>
</div>
</template>
Link showing when clicking the router link

Vue app fails to load component on standalone (no error message)

The app works fine on every browser, but when I "Add it to my Home Screen" on my iPad, it loads only the "main" component but none of the children.
Here's my main.js :
import Vue from 'vue'
import router from './router'
import App from '#/App.vue'
Vue.config.productionTip = false
const app = new Vue({
router,
render: (h) => h(App)
}).$mount('#app')
My App.vue :
<template>
<div id="app">
<div class="bg">BEFORE VIEW</div>
<router-view class="view"></router-view>
<div class="bg">AFTER VIEW</div>
</div>
</template>
<script>
require('./assets/styles.css')
</script>
My router/index.js :
import Vue from 'vue'
import VueRouter from 'vue-router'
import Parent from '#/components/Parent'
Vue.use(VueRouter)
export default new VueRouter({
mode: 'history',
base: __dirname,
routes: [
{ path: '/', component: Parent },
{ path: '/products',
component: Parent
},
{ path: '/clients',
component: Parent
},
{ path: '/verticals',
component: Parent
}
]
})
and the components/Parent.vue :
<template>
<div class="parent">
<p>INSIDE PARENT</p>
</div>
</template>
<script>
export default {
name: 'Parent'
}
</script>
Basically this is meant to be a kind of slide show, the Parent component will detect the current Route and go to the appropriate slide.
As I mentionned, the app works very well both on my desktop (on Chrome) and on my iPad (on Safari), but when I do "Add it to my home screen", all I see are the "BEFORE VIEW" and the "AFTER VIEW" from the App.vue (and the #app element has the right background color) but everything in the just doesn't load.
I feel like an idiot, I'm sure the solution just depends on a tidbit of knowledge I'm missing, but I can't seem to find anyone else with a problem close enough to mine that I can use their solution.
Please help, thank you so much for your time !
I randomly found a solution that makes the desired content appear.
In router/index.js, I removed the line
mode: 'history',
I honestly don't understand yet why it worked, but it does. I'll look further.
Thanks to everyone who took a look at my problem !

vue-router this.$route.params is empty

I'm trying to get a variable called project_id from the address bar using vue-router. I've initialized a router like so:
import Vue from 'vue'
import VueRouter from 'vue-router'
import App from './App'
Vue.config.productionTip = false
Vue.use(VueRouter)
/* eslint-disable no-new */
const router = new VueRouter({
routes: [
{ path: '/project/:project_id', component: App }
]
})
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
And tried to access this.$route.params.project_id from within my App.vue componenet:
<template>
<div id="app">
<img src="./assets/logo.png">
<div id="center_bar">
oh: {{this.$route.params.project_id}}
</div>
</div>
</template>
<script>
import ProjectList from './components/ProjectList'
import ProjectAboutBox from './components/ProjectAboutBox'
export default {
name: 'App',
created() {
console.dir(this.$route.params)
},
components: {
ProjectList,
ProjectAboutBox
}
}
</script>
However, when I write this.$route.params to the console, I see that it is an empty object.
I didn't see anyone who encountered something similar, so my guess is that I'm missing something very basic, but I can't figure out exactly what it is.
In addition, if I console.dir(this.$route) I'm seeing that fullPath is "/", even though I'm accessing http://localhost:8080/project/kljkjkj/
EDIT:
I have also found that when I create a <router-link> that leads to the address I want to parse, then clicking on it make the whole thing work, just accessing it directly by typing the address in the address bar fails
I come across a similar problem.
When manually enter url or refresh the browser, the $route object is not populated.
After some investigation, I found that if a lazy-loading route is matched:
For components outside 'router-view':
the $route object is not being populated even in the 'mounted' hook, but is populated later in the rendering process.
For components inside 'router-view':
the $route object is populated and available immediately
My fix is to use 'computed' property instead of 'data' when try to access variable inside the $route object.
Version:
"vue": "^2.6.11",
"vue-router": "^3.2.0"
Node: Changing the mode from 'hash' to 'history' doesn't help in my case.
Default vue-router is hash mode. You can try visit http://localhost:8080/#/project/kljkjkj/
You can change to history mode
const router = new VueRouter({
mode: 'history',
routes: [{ path: "/project/:project_id", component: App }]
});
Demo: https://codesandbox.io/s/p9v3172x6j (try to change url to https://p9v3172x6j.codesandbox.io/project/1234)
when in <template>you don't need to refer this.
have you tried:
<template>
<div id="app">
<img src="./assets/logo.png">
<div id="center_bar">
oh: {{$route.params.project_id}}
</div>
</div>
</template>
?
Also, I see that you are not using a <router-view>:
https://router.vuejs.org/api/#router-view