Why does every component in my page appears twice? - javascript

I have created a sort of First page for my project, but I don't know why it renders everything twice on my page:
here is my First.vue component that is used by the router as the first page:
<template>
<h1>Bienvenue</h1>
<router-view></router-view>
<div class="routing" v-if="this.$route.path == '/'">
<router-link to='/app'>Go to application</router-link>
<br>
<router-link to='/test'>Go to test</router-link>
</div>
</template>
and here is what I get on the page when I npm run serve
Does anyone knows where it comes from?
UPDATE
When I delete the router-view element, the components appear once but when I click on one of the links, it changes the URL of the page but the page in itself is not showing the component.
And when I try to put everything in my router-view, like this:
<template>
<router-view>
<div class="routing" v-if="this.$route.path == '/'">
<h1>Bienvenue</h1>
<router-link to='/app'>Go to application</router-link>
<br>
<router-link to='/test'>Go to test</router-link>
</div>
</router-view>
</template>
it appears once, but like the other case, when I click on a link, it is just changing the URL and not the page.
Here is my index.js to show you how my routes are defined:
import {createRouter, createWebHistory} from 'vue-router'
import App from '../App.vue'
import Test from '../Views/Test.vue'
import First from '../Views/First.vue'
export const router = createRouter({
history: createWebHistory(),
routes: [
{
path:'/',
name: 'First',
component: First,
},
{
path:'/test',
name: 'Test',
component: Test
},
{
path:'/app',
name: 'App',
component: App
}
]
})
Just to clarify what results I expect from my app:
When I run the project, I want to launch on a page with just a header saying 'Hello' at the top of the page and two links where I can either click on 'Go to the application' or 'Go to test'.
Then, when I click on one of the links, I want to see the content of the component (so either test or the app), but I don't want to see the header and the links anymore.

I am not sure but try this:
{
path: "/app",
component: () => import("../App.vue"),
name: "App"
},
{
path: "/test",
component: () => import("../Views/Test.vue"),
name: "Test"
},
{
path: "/",
component: () => import("../Views/First.vue"),
name: "First"
}

Update with sample code or you can refer to live code here.
// App.vue
const First = {
template: `<div class = "container" id="app">
<h1>Hi from First</h1>
<hr>
<router-link to="/foo">Foo</router-link>
<router-link to="/bar">Bar</router-link>
</div>
`
}
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }
const routes = [
{
path:'/',
name: 'First',
component: First,
default: First
},
{
path:'/foo',
name: 'Foo',
component: Foo
},
{
path:'/bar',
name: 'Bar',
component: Bar
}
]
const router = new VueRouter({
routes
})
const app = new Vue({
router
}).$mount('#app')
// main.js
<div id="app">
<!-- route outlet -->
<!-- component matched by the route will render here -->
<router-view></router-view>
</div>

Related

True or False to show route-item in navbar

im building a website and using vvue with vue-router.
My Navbar component iterates through the routes element and gets all routes to show in the navbar, so i can simply add and remove routes without changing the navbar component.
Now i want for example the Data protection notice or the legal notice not to show up.
I tried to solve this with a boolean and a v-if. Do you have any idea how to solve this problem?
My code looks as following:
Navbar component:
<template>
<div>
<div class="mdheader"></div>
<div class="md-layout-item">
<md-tabs md-sync-route class="md-primary" md-alignment="centered">
<div
v-for="r in this.$router.options.routes"
:key="r.name"
:v-if="r.showOnBar"
>
<md-tab :md-label="r.name" :to="r.path" exact></md-tab>
</div>
</md-tabs>
</div>
</div>
</template>
<script>
export default {
name: "navbar"
};
</script>
router/index.js
import Vue from "vue";
import VueRouter from "vue-router";
import Home from "#/views/Home.vue";
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "Home",
component: Home,
showOnBar: true
},
{
path: "/about",
name: "About",
showOnBar: true,
component: () => import("#/views/About.vue")
},
{
path: "/aktuelles",
name: "Aktuelles",
showOnBar: true,
component: () => import("#/views/Aktuelles.vue")
},
{
path: "/datenschutz",
name: "Datenschutz",
showOnBar: false,
component: () => import("#/views/Datenschutz.vue")
}
];
const router = new VueRouter({
routes
});
export default router;
Thanks in advance
Youa re very close, but you need to wrap your custom property in meta option:
const routes = [
{
path: "/",
name: "Home",
component: Home,
meta: { showOnBar: true }
},
{
path: "/about",
name: "About",
meta: { showOnBar: true }
component: () => import("#/views/About.vue")
},
{
path: "/aktuelles",
name: "Aktuelles",
meta: { showOnBar: true },
component: () => import("#/views/Aktuelles.vue")
},
{
path: "/datenschutz",
name: "Datenschutz",
meta: { showOnBar: false }
component: () => import("#/views/Datenschutz.vue")
}
];
and access it via route.meta.showOnBar. Keep in mind that you only need to define it for routes you want to show on your navbar.
You need to wrap your custom route properties into meta as stated in BroiSatse's answer.
However, another issue is that you used :v-if (i.e. you bound the v-if attribute) instead of just using v-if. v-if already evaluates the condition in the value as per the docs.
Here's a sandbox to play around with: https://codesandbox.io/s/stack-overflow-q-62409392-6zovw?file=/src/router/index.js

Vue router doesn't route to specified location

I'm using vue with vue-router and route doesn't work when routing to children route.
{
path: '/user',
name: 'User',
component: User,
children: [
{
path: 'profile',
component: Profile,
},
],
}
Programmatically routing to /user/profile
<template>
<div>
<button #click="goToUserProfile()">create new</button>
</div>
</template>
<script>
export default {
methods: {
goToUserProfile() {
this.$router.push('/user/profile') // Routing doesn't work
.catch(console.log);
},
},
};
</script>
give a route name "Profile" for "/user/profile"
{
path: '/user',
name: 'User',
component: User,
children: [
{
path: 'profile',
name: "Profile",
component: Profile,
},
],
}
navigation use route name
this.$router.push({name: "Profile"});
your User component should declare like this
User.vue
<template>
<div>
<p>this is user component</p>
<!-- your Profile component will replace this route-view -->
<route-view />
</div>
</template>
demo
https://codesandbox.io/s/falling-bash-6dl7m
Do your ensure that you put <router-view></router-view> in User Component template to make the nested (children) routes displayed.
<template>
<div>
<button #click="goToUserProfile()">create new</button>
<router-view></router-view> <!-- placeholder for children routes -->
</div>
</template>
Then you can access by both
this.$router.push('/user/profile') and this.$router.push({ name: 'UserProfile' })
As Vue router document states:
To render components into this nested outlet, we need to use the children option in VueRouter.
https://router.vuejs.org/guide/essentials/nested-routes.html
Hope this help.

The page loads twice in vue

I'm having trouble writing vue. I am using vue and vuetify.
There are A andB pages. There is no problem with entering the A orB page only once.
However, when the page is entered as below, the created function of A is called twice.
A -> B -> A
menuselector.vue
<template>
<v-list>
<template v-for='(eachmenu) in menu'>
<v-list-item
:to='eachmenu.path'
>
<v-list-item-title>
{{eachmenu.title}}
</v-list-item-title>
</v-list-item>
</template>
</v-list>
</template>
<script>
export default {
name: 'selector',
data() {
return {
menu: [
{
title: 'A',
path: '/A',
}
{
title: 'B',
path: '/B',
}
]
}
}
}
</script>
router.vue
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
redirect: '/A',
component: TestComponent,
children: [
{
path: 'A',
component: () => import('#/component/A.vue'),
name: 'Acomponent',
},
{
path: 'B',
component: () => import('#/component/B.vue'),
name: 'Bcomponent',
}
]
}
]
})
A.vue&B.vue
<template>
test
</template>
<script>
export default {
beforeCreate() {
console.log('beforeCreate');
}
created() {
console.log('created');
}
}
</script>
Console output is below.
what was problem???
I don't think "loading" is correct word here. Code needed for component is loaded from server only once as you can check in Dev Tools Network tab
When switching routes, component for old route is destroyed and component for new route is created. Its default behavior of Vue dynamic component (it is what <router-view> uses for switching components). You can change that by using <keep-alive>. Be sure to check documentation and understand implications - your app will use more memory
<keep-alive>
<router-view :key="$route.fullPath"></router-view>
</keep-alive>

Vue Router: hide parent template when child is open

Im trying to install Vue.js with the router and im running into some view issues. I have a router.js with child routes. I want to use this method for simple breadcrumbs and generate a clear overview so i know which route belongs where.
Opening each route works like a charm, everything shows up. When i open /apps I get a nice view from my Apps.vue that displays App overview</h1>. But now im opening /apps/app-one and then I see the Apps.vue and AppOne.vue template. How can I prevent that both templates are displayed?
The vue components looks like this:
Router.js
import Router from 'vue-router';
import AppsPage from './components/Apps.vue'
import AppOne from './components/AppOne.vue'
import AppTwo from './components/AppTwo.vue'
export default new Router({
// mode: 'history',
routes: [
{
path: '/apps',
component: AppsPage,
children: [
{
path: '/apps/app-one',
component: AppOne,
},
{
path: '/apps/app-two',
component: AppTwo,
},
]
},
]
});
Apps.vue
<template>
<div id="app-overview">
<h1>App overview</h1>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'app_page'
}
</script>
App1.vue
<template>
<div>
<h1>App 1</h1>
</div>
</template>
<script>
export default {
name: 'app_one'
}
</script>
App2.vue
<template>
<div>
<h1>App 2</h1>
</div>
</template>
<script>
export default {
name: 'app_two'
}
</script>
Having your routes in a parent-child relationship means that the child component will be rendered inside the parent component (at the <router-view>). This is expected behavior.
If you do not want the parent component to be visible when the child route is active, then the routes should be siblings, not nested:
[
{
path: '/apps',
component: AppsPage,
},
{
path: '/apps/app-one',
component: AppOne,
},
{
path: '/apps/app-two',
component: AppTwo,
},
]
The structure of the routes reflects the way they are rendered on the page.
It's possible and pretty easy too.You can achieve this by followings:
<template>
<div>
<div v-show="isExactActive">
Parent component contents will be here
</div>
<router-view ref="rv"></router-view>
</div>
</template>
<script>
export default {
data() {
return {
isExactActive: true,
}
},
updated() {
this.isExactActive = typeof this.$refs.rv === 'undefined';
},
mounted() {
this.isExactActive = typeof this.$refs.rv === 'undefined';
}
}
</script>
Hope, this will be helpful.

In Vue.js how to use multiple router-views one of which is inside another component?

I have a Vue.js single page application where there is a main navbar that uses <router-view/> to render different pages.
Something like this:
<main-header/> <!-- navigation links -->
<transition name="slide-fade" mode="out-in">
<router-view/> <!-- different pages -->
</transition>
In one of those pages I have a sidebar that has more navigation links (that are using <router-link/> just like the main navbar.
Something like this:
<sidebar/> <!-- navigation links -->
<div class="content">
<transition name="slide-fade" mode="out-in">
<router-view/> <!-- content beside the sidebar -->
</transition>
</div>
When I click on the sidebar navigation links I want the content beside the sidebar to change as well as the url to change. However, I lose the sidebar, and just get the component that is to be rendered in the content section.
How do I achieve the desired result? How do I use multiple <router-view/>s one of which is inside another component, like the example above?
You need to use named views. Provide the name attribute to the view.
<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
And configure them like
const router = new VueRouter({
routes: [
{
path: '/',
components: {
default: Foo,
a: Bar
}
}
]
})
Please refer to the official docs.
The reason the sidebar disappeared is all the components are rendered in the first <router-view> besides the <main-header>.
You should use the nested router by configuring children in the sidebar router like:
const router = new VueRouter({
routes: [
{ path: '/your-sidebar-url', component: your-sidebar-page,
children: [
{
// A will be rendered in the second <router-view>
// when /your-sidebar-url/a is matched
path: 'a',
component: A
},
{
// B will be rendered in the second <router-view>
// when /your-sidebar-url/b is matched
path: 'b',
component: B
}
]
}
]
})
More info in nested routes
#adoug answer helped me.
But in my case, I had named both router-view:
I did this to fix it:
<router-view name='a'/>
<router-view name='b'/>
You have , somewhere inside you FatherComponent.vue mounted in a you have a second
I did this, to fix it:
const router = new VueRouter({
routes: [
{ path: '/your-sidebar-url',
components: {
a: FatherComponent //you sidebar main component in 'a' name of routed-view
},
children: [
{
// A will be rendered in the second <router-view>
// when /your-sidebar-url/a is matched
path: '/child-path/a',
components: {
b: ChildComponentA //note that 'b' is the name of child router view
}
},
{
// B will be rendered in the second <router-view>
// when /your-sidebar-url/b is matched
path: '/child-path/b',
components: {
b: ChildComponentB //note that 'b' is the name of child router view
}
}
]
}
]
})
Named Route views
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }
const Baz = { template: '<div>baz</div>' }
const router = new VueRouter({
mode: 'history',
routes: [
{ path: '/',
// a single route can define multiple named components
// which will be rendered into <router-view>s with corresponding names.
components: {
default: Foo,
a: Bar,
b: Baz
}
},
{
path: '/other',
components: {
default: Baz,
a: Bar,
b: Foo
}
}
]
})
new Vue({
router,
el: '#app'
})
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
<h1>Named Views</h1>
<ul>
<li>
<router-link to="/">/</router-link>
</li>
<li>
<router-link to="/other">/other</router-link>
</li>
</ul>
<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>
</div>
https://router.vuejs.org/guide/essentials/named-views.html#nested-named-views

Categories