Is there any way to have dynamic routes/components in vuejs router?

2k Views Asked by At

Hi beautiful Vuejs developers out there! I have a little problem with routing many Vue components/pages dynamically. In this scenario I am using nested routes to have a couple of routes for my layout components and hundreds of child routes for my pages and as you can imagine I'll have to type many child routes statically or manually, and then add more when I need more child routes in the future code changes but I need a solution to simplify/solve this problem with more efficient/better way like adding those routes from what user types after the layout in the url... here is my example code code:

const routes: RouteRecordRaw[] = [
{
  {
    path: '/student',
    component: () => import('layouts/StudentLayout.vue'),
    children: [
      {
        path: 'dashboard',
        component: () => import('pages/student/Dashboard.vue'),
      },
      {
        path: 'profile',
        component: () => import('pages/student/Profile.vue'),
      },
    ],
  },
}

As you see in this code I have a layout named Student and it has two children but I'll have to type manually hundreds of child routes for this layout and other layouts is there any way to dynamically set up those routes with what users enter after the layout name like /student/dashboard or /layout/page and match it with a component name? I mean like params in Angular, can I use the param value itself inside the router to say?

 {
    path: ':pagename',
    component: (pagename) => import('pages/student/' + pagename + '.vue'),
 },

let me know if there is an efficient way to solve this problem. Thanks in advance!

1

There are 1 best solutions below

4
On BEST ANSWER

I would, personally, not use this, or advise such an approach, nor have I done it, but this idea came to me when I read your question:

My best guess would be to have a handler component which renders a component dynamically based on a route parameter (say you have /:subpage as a child to /student and the handler component is set to that route), and an exception handler around that to show a 404 page when the user types in an inexistent/unsupported route.

For example, I would dynamically import the component by the route parameter into a predefined let (e.g. let SubpageComponent; outside the try catch block), have a try catch block around the dynamic import assignment for the respective error where catch would set the variable to a 404 page. Then I would add the SubpageComponent into the data() of the component doing the rendering of the route.


Edit

I've written out come code that, maybe, makes sense.

It's based on https://v2.vuejs.org/v2/guide/components.html#Dynamic-Components

your routes definition, changed

const routes: RouteRecordRaw[] = [
    {
        path: '/student',
        component: () => import('layouts/StudentLayout.vue'),
        children: [
            {
                path: '/:subpage',
                component: () => import('pages/student/SubpageRenderer.vue'),
                props: true,
            },
        ],
    },
]

SubpageRenderer.vue

<script>
export default {
    props: ['subpage'],
    data() {
        return {
            currentSubpage: () => import(`./${subpage}.vue`)
        }
    }
}
</script>

<template>
    <component :is="currentSubpage"></component>
</template>

Instead of using the currentSubpage import, you can also use the subpage route prop to bind :is if subpage is the name of a registered component.

Since this would get only "dashboard" from the route, you'd need some namespacing, like "student-dashboard" with the help of template literals. You could make currentSubpage into a template literal that creates the student-${subpage} name.

I'd probably recommend importing the options object of the component designated by the subpage route parameter instead of registering all the components - if you're registering them, you might as well use vue-router the usual way :)

Also, I only think this could work! It should be tested out, and perhaps casing should be kept in mind, and maybe the Layout suffix as well (subpage will probably be all lowercase, and you'll probably have the components named in PascalCase). After uppercasing the first letter, this could also obviously lead to both /student/Dashboard and /student/dashboard being valid routes