Dynamic routing
Here you use vue3 and vite to implement dynamic routing, click here to viewEffect Source Code
Use scenarios
In the background management system, different routes can be returned according to the different logged-in users, and the page will also generate corresponding menus based on these routes. In this way, the content that a user can access can be controlled through the server.
For example, administrators can see server logs and system settings, but ordinary users cannot access these pages.
step
Define the basic routing table
There are some routes that can be accessed without logging in, such as login and 404 pages. These routes must be written in advance and added to the router.
Writing routing components
All routing components must be written in advance and placed in the /views directory.
Add a route
Define the addRoute() method, obtain the server route after logging in and add the route through this method
Generate menu
The routed meta field can add some menu-related information, such as menu name, icon, sorting, etc. Iterate through the routing list and generate the corresponding menu based on the meta information.
Code
Server routing data
Here we simulate the data returned by the server. For convenience, only one route is written.Source codeThere are more examples.
The meta data is determined by yourself and must be connected with the backend.
[ { path: '/user', component: 'DEFAULT_LAYOUT', meta: {menuName: 'user', order: 1}, children: [ { path: 'info', name: 'userInfo', component: 'user/info', meta: {menuName: 'Personal Center'} } ] } ]
Notice
- Only support secondary routing, that is, there can be no subroutine under subroutine
- Each level of route has at least one subroutine, even if you only want to show a menu. Because the parent route needs to display layout components, the child route is where the content is really displayed.
- component: 'DEFAULT_LAYOUT' means the layout component to be used for this route and needs to be defined in advance.
- meta: {menuName: 'user', order: 1}menuName represents the name of this menu, order represents the order of the menu, and other content can be added, such as
- Only one subroutine does not want to generate a secondary menu, so you can set single: true
- This field must be set for the name of the subroutine, and the entire route cannot be repeated. You need to use it to navigate when clicking a menu.
- The component of the subroutine indicates the location of the routing component, and all routing components need to be written in the /views directory in advance. For example, user/info here
- Import('@/views/user/') will actually be imported. Note: The paths must be separated by/
- meta: {menuName: 'Personal Center'} subroutines must define menuName, because subroutines will generate menus that users can click on, and will not be displayed without a name.
Add a route
Suppose that the login is successful now, start calling the addRoute() method to add routes. This method is placed where you need it according to the situation. It is all put together for the demonstration here.
// /components/ import { ref } from 'vue' import { useRouter } from 'vue-router' // This layout component needs to be defined in advanceimport DEFAULT_LAYOUT from '@/components/' const server_route = ref([]) const addRoute = async () => { // If there is no routing information locally, get it from the server if (!server_route.) { // Here we simulate getting data from the server, and we actually need to get data from the backend const { default: routes = [] } = await import('@/router/server_route') server_route.value = routes } // Convert the component field of the routing table into a real route server_route.((_route) => { if (_route.component === 'DEFAULT_LAYOUT') { _route.component = DEFAULT_LAYOUT } const children = _route.children // Dynamically import routing components according to string if ((children) && children?.length > 0) { ((childRoute) => { const path = ('/') if ( === 1) { = () => import(`@/views/${path}.vue`) } else { = () => import(`@/views/${path[0]}/${path[1]}.vue`) } }) } }) // Sort server_route.((a, b) => (a?.meta?.order ?? 0) - (b?.meta?.order ?? 0)) // Add routes in loop server_route.((route) => (route)) }
The data obtained from the server will be saved to server_route. The actual development should be saved to local localStorage, otherwise all refresh routes will disappear.
The data obtained cannot be used yet, because the component field is still a string, so you have to convert it into lazy loading to import the component.
// Convert the component field of the routing table into a real routeserver_route.((_route) => { if (_route.component === 'DEFAULT_LAYOUT') { // Set up the layout component, you can set multiple layouts for the project. The server only needs to modify this, and the front-end can display multiple layouts. _route.component = DEFAULT_LAYOUT } const children = _route.children // Dynamically import routing components according to string if ((children) && children?.length > 0) { ((childRoute) => { const path = ('/') // Use the dynamic import function provided by vite to import components from the views directory according to strings // Reference: /guide/#dynamic-import if ( === 1) { // If it is a single vue file = () => import(`@/views/${path[0]}.vue`) } else { // Otherwise it's a directory = () => import(`@/views/${path[0]}/${path[1]}.vue`) } }) } })
Because the parent component has fewer layout components, you generally don’t need to lazy load and import them all. Just select the corresponding layout according to the string.
Subcomponents need to be imported dynamically. vite provides a method to dynamically import modules based on variables.
If component: 'user/info'
- First, const path = ('/') split the path, at this time path = ['user', 'info']
- Because import() can only penetrate one layer of files according to variable import. If you import user/info directly, an error will be reported. You need to split it first and then splice it together.
- Then dynamically import the route according to the path and assign it to the component field of the subroutine. You need to ensure that there are such components in the /views directory
// The path must start with an absolute path, a relative path or @, end with a file name, and the vite official website has instructions// If it does not match, the import error will be reported = () => import(`@/views/${path[0]}/${path[1]}.vue`)
If component: 'welcome'
- At this time, the path of the component is equal to path = ['welcome']
- Then dynamically import
= () => import(`@/views/${path[0]}.vue`)
The above code has no subroutines under the default subroutine. If there are many level of routes, more judgments are needed.
After conversion, the component has been converted into a real component. The converted server_route
import DEFAULT_LAYOUT from '@/components/' server_route.value = [ { path: '/user', component: DEFAULT_LAYOUT, meta: {menuName: 'user', order: 1}, children: [ { path: 'info', name: 'userInfo', component: () => import('@/views/user/'), meta: {menuName: 'Personal Center'} } ] } ]
Sort it and then you can add it directly to the router.
import { useRouter } from 'vue-router' const router = useRouter() // Sortserver_route.((a, b) => (a?.meta?.order ?? 0) - (b?.meta?.order ?? 0)) // traverse the converted routing table and add routesserver_route.((_route) => (_route))
Generate menu
With routing data, you can generate a menu below. Here you will only generate a menu for the data returned by the server_route server. Locally defined routes will not be added to the menu.
<!-- /components/ --> <template> <div> <nav> <h1>Menu Bar</h1> <div style="display: flex; gap: 50px; align-items: flex-end;"> <template v-for="menu in server_route"> <!-- Show multi-level menu--> <div v-if="!"> <h5>{{ }}</h5> <button v-for="child in " @click="({name: })"> {{ }} </button> </div> <!-- Only display the first-level menu--> <div v-else> <button @click="({name: [0].name})">{{ [0]. }}</button> </div> </template> </div> </nav> <hr> <button v-show="needAddRoutes" @click="login">Simulate login to get routing</button> <main> <router-view /> </main> </div> </template>
The above code is just a demonstration, and actual development should define a separate layout-aside component specifically for rendering menus.
Summarize
Dynamically adding routing is done as long as the server data is defined in advance and the format is agreed upon, it is still very simple to do. As long as the component can be imported correctly according to the component field, there will be no big problem.
However, this is just a simple example, and there are still many situations to deal with in actual development.
This is the article about the implementation example of vue3 dynamic routing + menu bar. For more related contents of vue3 dynamic routing + menu bar, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!