Search code examples
vuejs2vue-router

Vue Router: Keep query parameter and use same view for children


I'm rewriting an existing Angular 1 application with Vue.

The application always needs to authenticate an user by locale, id and token before entering any views. Respecting the conventions of our API, I specified the token as a query parameter within my main parent route.

Coming from the existing Angular's UI router implementation I thought this is the way to go:

// main.js
new Vue({
  el: '#app',
  router,
  store,
  template: '<router-view name="main"></router-view>'
})

// router.js
const router = new Router({
  mode: 'history',
  routes: [
    {
      name: 'start',
      path : '/:locale/:id', // /:locale/:id?token didn't work
      query: {
        token: null
      },
      beforeEnter (to, from, next) {
        // 1. Get data from API via locale, id and token
        // 2. Update store with user data
      },
      components: {
        main: startComponent
      },
      children: [{
        name: 'profile',
        path: 'profile',
        components: {
          main: profileComponent
        }
      }]
    }
  ]
})    

When I navigate to the profile view, I expect the view to change and the query token to stay, e.g. /en-US/123?token=abc to /en-US/123/profile?token=abc. Neither happens.

I'm using Vue 2.3.3 and Vue Router 2.3.1.

Questions:

  • Can I keep query parameters when navigating to child routes?
  • Am I using the Vue router right here? Or do I need to blame my UI router bias?

Solution

  • You can resolve this in the global hooks of Router

    import VueRouter from 'vue-router';
    import routes from './routes';
    
    const Router = new VueRouter({
      mode: 'history',
      routes
    });
    
    function hasQueryParams(route) {
      return !!Object.keys(route.query).length
    }
    
    Router.beforeEach((to, from, next) => {
       if(!hasQueryParams(to) && hasQueryParams(from)){
        next({name: to.name, query: from.query});
      } else {
        next()
      }
    })
    

    If the new route (to) does not have its own parameters, then they will be taken from the previous route (from)