Why does Vue router-link not Work on Click - vue.js

I have the following nav bar component which should link to my about page view. When I mouse over a router-link element I can see Chrome telling me it should go there:
But when I click a link it does not go there.
NavBar.vue component template:
<template>
<nav>
<input class="search-bar" type="text" placeholder="Search Creators..." />
<ul class="menu-div">
<router-link to="/about">Pricing</router-link>
<router-link to="/about">Hello</router-link>
<router-link to="/about">Goodbye</router-link>
<router-link to="/about">Onetwo</router-link>
<button class="sign-up">Sign Up</button>
</ul>
</nav>
</template>
Here is my app.vue template
<template>
<div id="app">
<nav-bar />
<router-view></router-view>
</div>
</template>
<script>
import NavBar from "#/components/NavBar.vue";
export default {
components: {
"nav-bar": NavBar
}
};
</script>
And my routes in my index.js
import Home from "#/views/Home.vue";
import Vue from "vue";
import VueRouter from "vue-router";
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "Home",
component: Home
},
{
path: "/about",
name: "About",
component () { import("#/views/About.vue") }
}
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes
});
export default router;
Why is my about view not showing up when I click the router-link tags in my nav bar?

You are just importing the component. You must return it.
Change
component () { import("#/views/About.vue") }
to
component () { return import("#/views/About.vue") }
Or you could import the component outside of the definition and use it
import Home from "#/views/Home.vue";
import Vue from "vue";
import VueRouter from "vue-router";
import About from "#/views/About.vue"
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "Home",
component: Home
},
{
path: "/about",
name: "About",
component: About
}
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes
});
export default router;
....

Related

Vue3 Router duplicated component

I'm creating an app using Vue3js and vue-router.
When the app is created, I get my first component duplicated.
My App.vue component is this:
<template>
<div class="container-fluid">
<nav class="navbar navbar-expand-md fixed-top">
<div class="menu-izq">
<router-link id="logo" class="menu-item" to="/">COVELESS</router-link>
<router-link class="menu-item" v-if="!this.userLogged" to="/login">Login</router-link>
<router-link class="menu-item" v-if="this.userLogged" to="/canvas">Canvas</router-link>
<router-link class="menu-item" v-if="this.userLogged" to="/dashboard">Dashboard</router-link>
</div>
<div class="menu-dcha">
<router-link class="menu-item" v-if="this.userLogged" v-on:click="vaciarStorage()" to="/login">Logout
</router-link>
</div>
</nav>
<router-view></router-view>
</div>
My router.js file is this
import { createRouter, createWebHistory } from
'vue-router'
import LoginMenu from './components/LoginMenu.vue'
import AllElement from './components/AllElement.vue'
import Dashboard from './components/Dashboard.vue'
import App from './App.vue'
const routes = [
{
path: '/',
name: 'Home',
component: App
},
{
path: '/login',
name: 'Login',
component: LoginMenu
},
{
path: '/canvas',
name: 'Canvas',
component: AllElement
},
{
path: '/dashboard',
name: 'Dashboard',
component: Dashboard
}
]
const history = createWebHistory();
const router = createRouter({
history,
routes,
});
export default router
And my app.js file is this
import './bootstrap';
import { createApp } from 'vue/dist/vue.esm-bundler'
import App from './App.vue'
import router from './router'
createApp(App).use(router).mount('#app');
So when the App component is mounted on #app, the navbar gets duplicated because it is mounting another App component at "/" path (I guess because it is defined at router.js like that). But if I remove the
{
path: '/',
name: 'Home',
component: App
}
route, then I'm never navigating to the index.
Here you can see both the App components.

Why do my Vue-router doesnt route to my pages?

I got my Vue.js application, i've installed vue-router, via npm i vue-router,
i got a router-link on my main page App.vue, and i want to redirect to my Inscription.vue.
I do go on the http://localhost:8080/inscription when i click on the router-link, but the view doesnt change, im still on my main page,
i don't understand why ? (i got no error)
My main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false;
new Vue({
router,
render: h => h(App)
}).$mount('#app')
Vue.use(router);
My router/index.js :
import Vue from 'vue'
import Router from 'vue-router'
import App from '../App.vue'
import Inscription from '../Inscription.vue'
Vue.use(Router)
const routes = [
{
path: '/',
name: 'Home',
component: App
},
{
path: '/inscription',
name: 'Inscription',
component: Inscription
}
]
const router = new Router({
mode: 'history',
routes: routes
});
export default router;
My App.vue simplified
<template>
<div class="acceuil_main">
<div class="navbar_element">
<router-link :to="{name: 'Inscription'}">Inscription</router-link>
</div>
</div>
</template>
<script>
export default {
name: "App",
data () {
return {
beers: null,
connected: false,
user: null
}
}
};
</script>
My Inscription.vue simplified
<template>
<div class="acceuil_main">
<a class="navbar_element">
Inscription
</a>
</div>
</template>
<script>
export default {
name: "Inscription",
data () {
return {
title: "Inscription",
connected: false,
user: null
}
}
};
</script>
a picture of my folder architecture
For router to actually work you need a <router-view> component somewhere in your app. The best place is probably the App component. Check the docs
<router-view> works as a placeholder - router put there the component configured for a route when the route is active.
In that sense your / route should probably not use App component but something else - create another component for example Home which will be displayed on the root route (/)
const App = Vue.component('App', {
name: "App",
template: `
<div class="acceuil_main">
<div class="navbar_element">
<router-link :to="{name: 'Inscription'}">Inscription</router-link>
</div>
<router-view></router-view>
</div>
`
})
const Inscription = Vue.component('Inscription', {
template: `
<div>Inscription</div>`
})
const routes = [{
path: '/inscription',
name: 'Inscription',
component: Inscription
}]
const router = new VueRouter({
mode: 'history',
routes: routes
});
new Vue({
router,
render: h => h(App)
}).$mount('#app')
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app"></div>

How to create a login screen which don't include App.vue components

I am creating a SPA which have a login screen and other views. But the problem I am facing is, the login screen view also includes in the Navigation bar but It should not be there. Then I used Router navigation which displays a navigation bar alone without any views I think it also guards the Login view also.
App.vue
<template>
<section id="app" class="hero">
<section class="main-content columns is-fullheight has-background-white-bis">
<Navigation />
<div class="hero-body">
<router-view />
</div>
</section>
</section>
</template>
<style>
.menu {
margin: 25px;
}
</style>
<script>
import Navigation from "#/components/Navigation.vue";
export default {
name: "app",
components: {
Navigation
}
};
</script>
router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [{
path: '/LoginUser',
name: 'login',
component: LoginUser,
},
{
path: '/',
name: 'dashboard',
component: Dashboard,
},
}]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
var isAuthenticated = false;
router.beforeEach((to, from, next) => {
if (!isAuthenticated) next('/LoginUser')
else next()
})
export default router
To remove the navigation when specifically on the Login route, you can add a v-if to your <Navigation /> component, which checks if the route is not on the login page:
<Navigation v-if="this.$router.currentRoute.name !== 'login'" />
We can conditionally render components by checking the name of the current route using v-if directive. I used this in a recent project.
My route index.js file
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import Login from '../views/Login.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/login',
name: 'login',
component: Login
},
{
path: '/register',
name: 'register',
component: Register
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
My App.vue file
<template>
<div id="app">
/* Note that this takes an array of route names, so you can simple pass in
the name of the route you dont want this component to be displayed on */
<navbar v-if="!['login', 'register', 'help'].includes($route.name)" />
<main>
<router-view />
</main>
<appfooter v-if="!['login', 'register'].includes($route.name)"/>
</div>
</template>

How to proper use vue-router?

I want to exclude the h1 tag every time I go to different route in my Vue application.
Here's my app.vue:
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<h1>LANDING PAGE</h1>
<router-view></router-view>
<!--Path for login.vue-->
<button #click="$router.push('/login')">LOGIN</button>
</div>
</template>
<script>
export default {
name: 'app',
}
</script>
And here's my login page, where I want only to display my design for login page only:
<template>
<div>
<h1>Login Page</h1>
</div>
</template>
<script>
export default {
name: "Login"
}
</script>
My route.js:
import Login from './components/LandingPage/Login';
import Register from './components/LandingPage/Register';
export default [
{
path: '/login', component: Login
},
{
path: '/register', component: Register
}
]
and lastly my main.js:
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
import Routes from './routes';
import VueResource from 'vue-resource'
Vue.config.productionTip = false;
Vue.use(VueRouter);
Vue.use(VueResource);
const router = new VueRouter({
routes: Routes,
/* To remove # in the URL */
mode: 'history'
});
new Vue({
render: h => h(App),
router: router
}).$mount('#app');
I didn't include the register.vue because it's just the same with login.vue.
Conditional rendering based on the landing page url:
<h1 v-if="$route.path === '/landing-page-url'">LANDING PAGE</h1>
Actually, there are three approaches to solve your problem:
Just drop your <h1></h1> into your landing page component.
You can use conditional rendering, like Psidom answered (just changed path to name):
<h1 v-if="$route.name === 'Landing'">Landing page</h1>
You can have only one <h1></h1> in your main layout, and render current page title dynamically. Route Meta Fields come in rescue.
import Login from './components/LandingPage/Login'
import Register from './components/LandingPage/Register'
export default [
{
path: '/login',
component: Login,
meta: {
title: 'Login',
},
},
{
path: '/register',
component: Register,
meta: {
title: 'Register',
},
},
]
And then in your template:
<h1>{{ $route.meta.title }}</h1>
P.S. To navigate to another route in your template use <router-link></router-link> instead of button with click event.

Vue router link add object in the url

This is my setting:
main.js creates a vue and attaches the component App to an element in the dom
router.js sets the routs
App.vue has the router-view and a few router-links
Problem:
the link <router-link to="/admin">Admin1</router-link> works fine
the link <router-link to="{name: 'admin'}">Admin2</router-link> doesn;t work and adds to the url bar: #/{name: 'admin'}
Am I using the router in the wrong way?
Below my files in details
main.js
import Vue from 'vue'
import router from './router'
import App from './App'
new Vue({
router,
el: '#app',
components: { App },
template: '<App/>',
data: {
}
})
router.js
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '#/components/HelloWorld'
import Marketplace from '#/components/Marketplace'
import Admin from '#/components/Admin'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
path: '/marketplace',
name: 'marketplace',
component: Marketplace
},
{
path: '/admin',
name: 'admin',
component: Admin
}
]
})
App.vue
<template>
<div id="app">
<p>
<router-link to="/">Home</router-link>
<router-link to="/admin">Admin1</router-link>
<router-link to="{name: 'admin'}">Admin2</router-link>
</p>
<router-view/>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
In order for your to="{name: admin}" to work without adding the char #, do the following inside your router config file.
Also you are supposed to use the v-bind for to="".
Use v-bind:to="{name: 'admin'}" or :to="{name: 'admin'}"
Example:
export default new Router({
mode: 'history',
// whatever you have
})
Source: https://router.vuejs.org/en/essentials/history-mode.html