Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue.js nested routing with default child

Tags:

vue.js

vuejs2

I have an issue with a default children route in Vue.js 2.

When I visit localhost/listings initially, it correctly loads index.vue and map.vue as a child.

When I navigate using router-link to localhost/listings/1, and then using router-link back to localhost/listings, then it still loads the show.vue template. This shouldn't happen?

I have no navigation guards or anything that should interfere. Is there anyway to correct this?

My routes:

window.router = new VueRouter({
  routes: [
    ...

    {
      path: '/listings',
      name: 'listing.index',
      component: require('./components/listing/index.vue'),
      children: [
        {
          path: '',
          component: require('./components/listing/map.vue')
        },
        {
          path: ':id',
          name: 'listing.show',
          component: require('./components/listing/show.vue')
        }
      ]
    },
    
    ...
  ]
});
like image 785
andershagbard Avatar asked Nov 22 '16 20:11

andershagbard


3 Answers

The "father" router should not be named if you want a default child route, so instead using :to="{name: 'listing.index'}", use the name of the default child route (e.g :to="{name: 'listing.map'}").

The code should look like this:

window.router = new VueRouter({
routes: [

    ...

    {
        path: '/listings',
        component: require('./components/listing/index.vue'),
        children: [
            {
                path: '',
                name: 'listing.map'
                component: require('./components/listing/map.vue')
            },
            {
                path: ':id',
                name: 'listing.show',
                component: require('./components/listing/show.vue')
            }
        ]
    },

    ...

  ]
});
like image 199
Sadraque Santos Avatar answered Nov 18 '22 14:11

Sadraque Santos


Maybe try re-arranging the children, routes are fired in the order they match from top-to-bottom, so this should hopefully fix it:

window.router = new VueRouter({
    routes: [

    ...

    {
        path: '/listings',
        name: 'listing.index',
        component: require('./components/listing/index.vue'),
        children: [
            {
                path: ':id',
                name: 'listing.show',
                component: require('./components/listing/show.vue')
            }
            {
                path: '',
                component: require('./components/listing/map.vue')
            },
        ]
    },

    ...

  ]
});

Just for a bit of clarification, your path: '' essentially serves as a "catch all", which is likely why when it's at the top it's being found immediately and so the router never propagates any further down to the :id route.

like image 30
K3TH3R Avatar answered Nov 18 '22 15:11

K3TH3R


In Vue 2.6.11 you can automatically redirect to a child route if parent route is hit:

const routes = [
  {
    name: 'parent',
    path: '/',
    component: Parent,

    children: [
      {
        name: 'parent.child',
        path: 'child',
        component: Child,
      }
    ],

    /**
    * @type {{name: string} | string} Target component to redirect to
    */
    redirect: {
      name: 'parent.child'
    }
  }
];
like image 1
user8555937 Avatar answered Nov 18 '22 16:11

user8555937