Recently, I used the addRoutes API of vue-router in my project and encountered a small pit. Let’s record and summarize it.
Scene reappearance:
Most of the students who do front-end development have encountered this requirement: the page menu is dynamically generated based on user permissions. A common solution is:
When the front-end initializes, it only mounts the routes without permissions, such as login, registration and other page routes. Then, after the user logs in, the back-end returns the permission table of the current user. The front-end traverses the front-end routing table based on this permission table, dynamically generates user permission routes, and then uses addRoutes provided by vue-router to dynamically add the permission routing table to the routing instance. The whole process is roughly as follows:
// document // Routing table that requires user permissionsconst appRoutes = [ { path: '/dashboard', name: 'dashboard', component: () => import('...'), children: [ RouteConfig1, RouteConfig2, ... ] }, RouteConfig, ... ]; // Routing table without user permissionconst constantRoutes = [ { path: '/login', name: 'login', component: Login }, { path: '/register', name: 'register', component: Register }, ... ] // When initializing the route, only mount the routing table that does not require user permissionsconst router = new VueRouter({ mode: 'history', base: .BASE_URL, constantRoutes }); /** * * If the data returned by the backend is as follows: * * { * status: 200, * message: 'successful', * data: { * user: {...}, * token: '...', * permission: [...] * } * } * * */ ('/user/login',{username,password}) .then(res => { if ( === 200) { // If the login is successful, you need to traverse the generated user permission route // filterRoutes generates dynamic routing tables based on permission and appRoutes defined in permission and const routes = filterRoutes(permission); // Then use addRoutes to mount routes into router (routes); } else { ... } }) .catch(error => { ... })
Having written this, it seems that the function of dynamically generating routing is good. Everything is perfect, but the problem comes immediately. After the user logs in, we click the logout button on the page to log out of the current login, and then log in again. We will find that the browser console panel will report the following error:
Nani (⊙o⊙)? What's going on? I logged in normally for the second login. There seems to be no problem with the function, but where does this warning come from? For a patient with severe obsessive-compulsive disorder, any warning or error is not allowed, even if there is no functional problem.
A look
This warning means that the above routes are named repeatedly, and there are multiple routes with the same name. So why are there multiple routes with the same route name?
Let's start with how this error came about. First of all, there is no problem when we open the website and log in for the first time. Only when we log out and log in again, this warning comes. And if we refresh the browser before logging in repeatedly, then log in, this warning will not appear, isn't it?
Let’s analyze the above scenario: First of all, this warning will only appear when the user logs in again. The only thing we do when logging in is to dynamically add routes, so the problem must be (routes). Secondly, there are two situations here: refresh and no refresh. This warning will be reported without refresh, and this warning will not be reported if refreshed. So what is the difference between refreshing and no refreshing?
It is easy to think that when the page is refreshed, the Vue instance will be re-initialized. During the initialization of the Vue instance, the Vue-Router, Store and other content mounted on it will be re-initialized. And without refreshing, it will not be reinitialized.
Think about it again, after we log in for the first time, we added the permission route routes to the router through addRoutes. Assuming that our permission routes include three routes dashboard, user, and role, then when we log out and log in again, since the same user logs in, the permission list returned by the backend is the same, and the generated dynamic route routes are the same (that is, it also contains three routes dashboard, user, and role). Then adding these three routes again at this time will cause the routes mounted in the router to be repeated. In the case of refresh, since the router is re-initialized, it only includes initializing the routes we added without permissions. When logging in again, there is no problem of duplication of routes when re-adding.
Through the above analysis, we have figured out the source of the problem, so how to solve it? Unfortunately, vue-router does not delete the routed API. Based on the above analysis, it is easy to think of resetting the router by force refreshing the page: that is, when the user logs out, force refresh the page through js. That can solve the problem. Although this method can solve the problem, it does not look very elegant, and refreshing the page causes resource reload and page flickering, so the experience is not particularly good. So is there a way to solve the problem without refreshing?
After some searching, I finally found a method, which is to reset the match attribute of the current router:
// Define a function to create routerexport const createRouter = routes => new VueRouter({ mode: 'history', base: .BASE_URL, routes }); // Where to use addRoutes// Reset the match of the current router = initial = createRouter(constantRoutes).match; (routes);
This will solve the problem perfectly.
Summarize:
The whole solution process is still quite painful, because in reality my code is relatively complicated and not as simple as the simplified above.
The entire addRoutes is completed in the middle, and there are also a series of functions such as generating dynamic routes and regenerating user menus based on dynamic routes. The interference is relatively large. This is a source code alarm, which is difficult to locate. It can only be debugged through console and browser, and the error range is narrowed step by step, and the cause of the problem is finally found.
Then find the solution step by step through Google and search for the issue of the vue-router repository.
So I want to say that if you encounter some third-party dependencies in development, you can search for the issue of the official repository. It is very useful, and many questions actually have answers in the issue. I've been tried and tested.
Finally, I must use Google and Baidu. I wasted a long time and I didn’t find anything.