I'm creating a Router instance in order to implement a routing system in my app. So, I'm doing it in such a way:
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Home',
component: Home
},
]
})
But I also need to implement a .beforeEach() hook on my Router instance. What's the workaround?
I find the way like:
router.beforeEach((to, from, next) => {
// ...
});
But I guess in my case it won't be correct? What's the proper way of doing it?
Solved:
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
const router = new Router({
routes: [
{
path: '/',
name: 'Home',
component: Home
},
]
})
Implementing .beforeEach() hook on router instance:
router.beforeEach((to, from, next) => {
if(to.meta.requiresAuth) {
if(store.state.session.authenticated) {
next();
}
else {
next('/admin/login');
}
}
else {
next();
}
});
Exporting the instance:
export default router;
Related
This question already has an answer here:
Is there a way to accees vue js VueSession in main.js
(1 answer)
Closed 1 year ago.
I use a vue-gapi https://www.npmjs.com/package/vue-gapi in my code to access Google Calendar API. I was successful to install and use this plugin to get data from Calendar API. I now struggle to use router guards.
plugins/vuagapi.js:
import Vue from 'vue';
import VueGapi from 'vue-gapi';
const apiConfig = {
apiKey: '***',
clientId:
'***.apps.googleusercontent.com',
discoveryDocs: [
'https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest',
],
scope: 'https://www.googleapis.com/auth/calendar.readonly',
prompt: 'select_account',
};
Vue.use(VueGapi, apiConfig);
router/index.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from '../views/Home.vue';
import Dashboard from '../views/Dashboard.vue';
import Login from '../views/Login.vue';
import '../plugins/vuegapi.js';
Vue.use(VueRouter);
const routes = [
{
path: '*',
redirect: '/',
},
{
path: '/',
name: 'Home',
component: Home,
},
{
path: '/login',
name: 'Login',
component: Login,
},
{
path: '/dashboard',
name: 'Dashboard',
component: Dashboard,
meta: {
authRequired: true,
},
},
];
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes,
});
router.beforeEach((to, from, next) => {
if (to.matched.some((record) => record.meta.authRequired)) {
if (this.$gapi.currentUser()) {
next();
} else {
alert('You must be logged in to see this page');
next({
path: '/login',
});
}
} else {
next();
}
});
export default router;
I am getting: vue-router.esm.js?8c4f:2314 TypeError: Cannot read property '$gapi' of undefined.
Anyone can point me to right direction? I am able to use this plugin in .vue files but not in another plain .js, suspecting that this $gapi exists only as Vue instakce property/method? As I am beginner I do not know how to import it properly.
if you wanna access Vue instance inside your router use router.app instead of this
change this line :
this.$gapi.currentUser()
to this:
router.app.$gapi.currentUser()
you can read more about Router Instance Properties in : https://router.vuejs.org/api/#router-instance-properties
The Idea
Let me first tell you the idea, user enter "domain.com" user will get redirected to "domain.com/en" where is set by default to the english language, after that user can navigate throughout the website for example to "domain.com/en/about-us/".
My Issue
I can't figure out how to set up the routing for the "domain.com/wrong-page" where is also the global i18n parameter that i'm waiting for or "domain.com/wrong-language/corect-page" so the user can get the appropriate 404 page that i want.
My Set Up
Router file
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import i18n from '../i18n'
Vue.use(VueRouter)
const routes = [
{
path: '/',
redirect: `/${i18n.locale}`
},
{
path: '/:lang',
component: {
render(c) { return c('router-view') }
},
children: [
{
path: '',
name: 'Home',
component: Home
},
{
path: 'about',
name: 'About',
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
},
{
path: '/*',
name: '404',
component: () => import(/* webpackChunkName: "404" */ '../components/404.vue')
}
]
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
Main.js file
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import i18n from './i18n'
import LanguageSwitcher from "#/components/LanguageSwitcher.vue";
import NavigationTopMenu from "./components/NavigationTopMenu.vue";
import Footer from "./components/Footer.vue";
Vue.component('language-switcher', LanguageSwitcher)
Vue.component('navigation-top-menu', NavigationTopMenu)
Vue.component('footer-g', Footer)
Vue.config.productionTip = false
// use beforeEach route guard to set the language
router.beforeEach((to, from, next) => {
// use the language from the routing param or default language
let language = to.params.lang;
if (!language) {
language = 'en'
}
// set the current language for i18n.
i18n.locale = language
next()
})
new Vue({
router,
store,
i18n,
render: h => h(App)
}).$mount('#app')
So, another developer reached out to me, the answer was pretty straight forward we can implement a custom regex for the lang to limit what can be matched with.
:lang
needs to be
:lang(en|fr|es)
another solution is to configure the navigation guard further and redirect to the following error page.
I'm asking for help. I use vuejs to make my application. Everything works perfectly. But I do the npm run build, I extract the dist folder and I open index.html, I have a blank page, and when I look in the console, I have no errors.
main.js
import Vue from "vue";
import Vuex from "vuex";
import router from "./router";
import App from "./App.vue";
import vuetify from "./plugins/vuetify";
import store from "./store";
import {
ValidationObserver,
ValidationProvider,
extend,
localize
} from "vee-validate";
import fr from "vee-validate/dist/locale/fr.json";
import * as rules from "vee-validate/dist/rules";
// install rules and localization
Object.keys(rules).forEach(rule => {
extend(rule, rules[rule]);
});
localize("fr", fr);
// Install components globally
Vue.component("ValidationObserver", ValidationObserver);
Vue.component("ValidationProvider", ValidationProvider);
Vue.config.productionTip = false;
//load vue-moment
Vue.use(require("vue-moment"));
//Load vuex
Vue.use(Vuex);
//Load vueRouter
new Vue({
router,
vuetify,
store,
render: h => h(App)
}).$mount("#app");
router/index.js
import Vue from "vue";
import VueRouter from "vue-router";
import Professeur from "../components/Professeur";
import Matiere from "../components/Matiere";
import Dashboard from "../components/Dashboard";
import Filiere from "../components/Filiere";
import Salle from "../components/Salle";
import Shedule from "../components/Shedule";
import SheduleLine from "../components/SheduleLine";
import Login from "../components/Login";
import Home from "../components/Home";
Vue.config.productionTip = false;
Vue.use(VueRouter);
const router = new VueRouter({
mode: "history",
routes: [
{
path: "/dashboard",
name: "dashboard",
component: Dashboard,
meta: {
requiresAuth: true
},
children: [
{
path: "personnel/professeurs",
name: "p_professeur",
component: Professeur
},
{
path: "",
name: "home",
component: Home
}
]
},
{
path: "/login",
name: "login",
component: Login,
meta: {
guest: true
}
}
]
});
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
let user = JSON.parse(localStorage.getItem("_GET_TOKEN"));
if (!user && !user.token) {
next({
name: "login"
});
} else {
next();
}
} else {
next();
}
});
export default router;
App.vue
<template>
<v-app>
<router-view/>
</v-app>
</template>
<script>
export default {
name: 'app',
}
</script>
Once I compile, I have no errors but a blank page.
Thanks for any help. I tried without the router view, I manage to launch the index.html once compiled for production and I have a rendering.
You're using history mode for your router, which means you'll access your pages with paths like /login or /dashboard or /dashboard/personnel/professeurs, which are the only routes you declared.
/ or /index.html does not display anything because the router doesn't know what they are.
However, in order to have history mode working, you cannot just have a static server. The server has to know that a request to /dashboard should return the index.html file.
If you used VueCLI, the docs here might be helpful:
If you are using Vue Router in history mode, a simple static file server will fail. For example, if you used Vue Router with a route for /todos/42, the dev server has been configured to respond to localhost:3000/todos/42 properly, but a simple static server serving a production build will respond with a 404 instead.
To fix that, you will need to configure your production server to fallback to index.html for any requests that do not match a static file. The Vue Router docs provides configuration instructions for common server setups.
If you don't want to deal with this, or don't have a server enabling you to do this, you can switch history to hash mode in your router. Your routes will be accessible at /index.html#/dashboard and so on.
If you are running into this issue (as I was) in 2022 with a serverless vue 3 application and vuex, you can configure the hash-histroy like so
import { createRouter, createWebHashHistory } from 'vue-router'
import { type RouteRecordRaw } from 'vue-router'
import { Admin, Welcome } from '/#/views'
const routes: RouteRecordRaw[] = [
{
path: '/',
name: 'Welcome',
component: Welcome
},
{
path: '/admin',
name: 'Admin',
component: Admin
}
]
const router = createRouter({
history: createWebHashHistory(), // <--- this is important
routes
})
export { router }
See also: docs
router/index.js :
import { createRouter, createWebHashHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
}
]
const router = createRouter({
history: createWebHashHistory(process.env.BASE_URL),
routes
})
export default router
main_folder/vue.config.js
const { defineConfig } = require('#vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave: false,
publicPath: ''
})
Important: use publicPath: '' and createWebHashHistory
That is all. You can now build. But remember that your links will appear as /index.html#/dashboard.
I am trying to guard home page and route user to login page if he/she is not signed in.
To do that I made I made router object so that I can use beforeEach() function.
But I get this error:
This error occurs after I try to make a constant object of router.
router.js is:
import Vue from 'vue';
import Router from 'vue-router';
import firebase from 'firebase';
import Home from './views/Home.vue';
import Signup from './components/auth/Signup.vue';
import Login from './components/auth/Login';
Vue.use(Router);
const router = new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'home',
component: Home,
meta: {
requiresAuth: true,
},
},
{
path: '/signup',
name: 'Signup',
component: Signup,
},
{
path: '/login',
name: 'Login',
component: Login,
},
],
});
// router guards
router.beforeEach((to, from, next) => {
// check to see if routh require auth
if (to.matched.some(rec => rec.meta.requiresAuth)) {
// check state of user
const user = firebase.auth().currentUser;
if (user) {
next();
} else {
next({ name: 'Login' });
}
} else {
next();
}
});
This is is in main.js file.
import Vue from 'vue';
import firebase from 'firebase';
import router from './router';
import App from './App.vue';
Vue.config.productionTip = false;
const app = null;
// Wait for firebase init the user
firebase.auth().onAuthStateChanged(() => {
// init the app if not created
if (!app) {
new Vue({
router,
render: h => h(App),
}).$mount('#app');
}
});
Add the below changes
Add this line to last in router.js
export default router;
Add In main.js
import router from './router'; (path should point to your router.js)
new Vue({
router,
....
....
})
I'm trying to implement the two level routing by using vue-router
main.js
import Vue from 'vue'
import Router from 'vue-router'
import Hello from '../components/Hello.vue'
import First from '../page/firstPage.vue'
import Login from '../page/logIn.vue'
import Second from '../page/secondPage.vue'
Vue.use(Router)
const routes =[
{
path: '/',
component: Login
},
{
path: '/first',
component: First,
children: [ {
path: 'hello',
component: Hello
}
]
},
]
const router = new Router({
mode:'history',
routes:routes
})
export default router
But when I input http://localhost:8080/first/hello, it returns the 'First' component not the 'Hello' component.
thanks a lot