Vuejs Router, conditional loading of JavaScript Code - javascript

I am integrating Vue Router into my application.
Within one of my components, I am using some js code which I do not want to load or be present when on another route?
Example
compA.vue
<script>console.log('hello')</script>
app.com/a -> I should see console log Hello.
app.com/b -> when I access this I should not see hello in the console.
EDIT: Clarifying based on the responses.
I have two components, each with own lifecycle hooks so I do not need to set logic to fire the function based on components...
If a user visits compA and the function fires and creates some side effects, when I visit compB I would like there to be no side effects similar to how a traditional route would work, because it would get the new code and render the page once more.

You could use the path variable accessible through $router in vue. Open your vue devtools, click on your component and click on $route on the righthandside. Here you can see all the variables accessible through $route
Example:
mounted() {
// console.log will only run on route '/a'
if (this.$route.path === '/a') {
console.log('Hello World)
}
}
If $route throws an error. You need to define this in your main.js
import router from './router'
new Vue({
el: '#app',
router,
store,
render: h => h(App)
})
in router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import Login from '#/app/Login/Login'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Login',
component: Login
}
]
})

you can add some meta data to your routing config:
const router = new VueRouter({
routes: [
{
path: '/a',
component: compA,
meta: { doLog: true }
},
{
path: '/b',
component: compA,
meta: { doLog: false }
},
]
})
and then you can use this.$route.meta.doLog in your component:
created() {
if(this.$route.meta.doLog) {
console.log('hello');
}
}

Related

VueJS i18n Routes 404 Page

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.

Npm run generate not generating routes

I am using vue-router in a nuxt project and when i run npm run generate it generates everything except my pages. I think it has got something to do with the router because before using vue router i had no problems with generating the pages Here is my router:
router.js
import Vue from 'vue'
import Router from "vue-router"
import Home from '../debonkelaer/pages/index.vue'
import actueel from '../debonkelaer/pages/actueel.vue'
import impressies from '../debonkelaer/pages/impressies.vue'
import reglement from '../debonkelaer/pages/reglement.vue'
import reserveren from '../debonkelaer/pages/reserveren.vue'
import tarieven from '../debonkelaer/pages/Tarieven.vue'
import ingelogd from '../debonkelaer/pages/ingelogd.vue'
import firebase from 'firebase/app'
import 'firebase/auth'
Vue.use(Router);
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/actueel',
name: 'Actueel',
component: actueel
},
{
path: '/impressies',
name: 'Impressies',
component: impressies
},
{
path: '/reserveren',
name: 'Reserveren',
component: reserveren
},
{
path: '/tarieven',
name: 'Tarieven',
component: tarieven
},
{
path: '/reglement',
name: 'Reglement',
component: reglement
},
{
path: '/ingelogd',
name: 'Ingelogd',
component: ingelogd,
}
]
const router = new Router({
mode: 'history',
base: '/',
routes
})
export function createRouter() {
return router
};```
If you need any additional code please reply.
When you're working with nuxt.js all routes are automatically generating from all your files in your pagesdirectory. That means you don't need to manually declare every route!
Be sure to check out the official documentation for nuxt.js: Automatic Routing
To check for auth you should use middleware.
If you only need it for one specific route/component, you can use something like the following code in your component's exported function
middleware({ redirect }) {
// If the user is not authenticated
const authenticated = YOUR_AUTH
if (!authenticated) {
return redirect('/login')
}
}

Watch changes in $route object - Vue Router

I'm doing a project of small CRM. In the login form, I have a component that shows an alert message when email or password is incorrect. When someone is trying to login incorrectly, then type the correct info and then logout, the message still appears unless the page is refreshed.
I tried to solve that within watch by accessing $route, so every time the route is changed, I clear the state of the message.
Alert.vue:
<template>
<div :class="'alert ' + alert.type">{{alert.message}}</div>
</template>
<script>
import { mapState, mapActions } from 'vuex';
export default {
computed: mapState({
alert: state => state.alert
}),
methods: mapActions({
clearAlert: 'alert/clear'
}),
watch: {
$route (to, from){
console.log('inside $rout');
this.clearAlert();
}
}
};
</script>
main.js:
import Vue from 'vue';
import { store } from './_store';
import { router } from './_helpers';
import App from './components/App';
import './css/main.css';
new Vue({
el: '#app',
router,
store,
render: h => h(App)
});
router.js:
import Vue from 'vue';
import Router from 'vue-router';
import Dashboard from '../components/Dashboard.vue';
import LoginPage from '../components/LoginPage.vue';
import UserPage from '../components/UserPage.vue';
Vue.use(Router);
export const router = new Router({
mode: 'history',
routes: [
{ path: '/app', component: Dashboard },
{ path: '/login', component: LoginPage },
{ path: '/app/user-info', component: UserPage },
{ path: '*', redirect: '/app' }
]
});
router.beforeEach((to, from, next) => {
const allowedPages = ['/login'];
const authRequired = !allowedPages.includes(to.path);
const loggedIn = localStorage.getItem('user');
if (authRequired && !loggedIn) {
return next('/login');
}
next();
})
I tried to do both methods in documentation https://router.vuejs.org/guide/essentials/dynamic-matching.html
For some reason, the $route isn't recognized & I can't access it.
I should also mention that in my main.js I import the router.js file which imports Router from 'vue-router' & instantiates it, so $route should be accessible from all components.
can someone shed some light on why?
link to my project: repo
The $route watcher setup you have is correct, and your component has access to $route, as can be seen if you log it in mounted().
The problem is that the watcher is in Alert.vue, which is a component that is on a page being navigated away from, so it gets destroyed, preventing the watcher being invoked. If you move the $route watcher to a component that is always kept alive (e.g., App.vue), you'll see that it works correctly.

vue-router showing blank page when built

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.

Trouble getting data from root Vue instance with vue-router

I load all of my data in the root Vue instance and im trying to access them in my router.
How can I access the data in my root instance within my router? All the this.a.app or this.app answers i found online weren’t the solution.
Router.js:
import Vue from 'vue'
import Router from 'vue-router'
import Login from '../components/login'
import Container from '../components/container'
Vue.use(Router)
export default new Router({
mode: 'history',
routes: [{
path: '/login',
name: 'Login',
component: Login,
props: { test: **<data from my Vue root instance>** }
},
{
path: '/products',
name: 'Container',
component: Container,
children: [{
path: 'flavor',
component: Login
},
{
path: 'storage',
component: Login
},
{
path: 'network',
component: Login
}
]
}
]
})
Main.js:
import router from './router’
var vm = new Vue({
el: ‘#app’,
router,
template: ‘’,
components: {
App
},
data() {
return {
modal: ‘’
I would avoid sharing the data using the router instance.
I personally like to have a store file, which contains data I want to share between my components.
export default {
state: {
counter: 0
}
}
And in your component you can import the file:
import store from '../store'
export default {
data () {
return {
sharedState: store.state
}
}
}
Changes to sharedState will also be passed to other components.
Source: https://skyronic.com/2016/01/03/vuex-basics-tutorial / Solution 2

Categories

Resources