Router and Nav
Router and Nav are the key skeleton for organizing a management system.
This project router and nav are bound together, so you only have to configure the route under @/router/index.js
and the sidebar nav will be dynamically generated automatically. This greatly reduces the workload of manually editing the sidebar nav. Of course, so you need to follow many conventions in configuring the route.
Config
First let us know what configuration items are provided config route.
// if set to true, lt will not appear in sidebar nav.
// e.g. login or 401 page or as some editing pages /edit/1 (Default: false)
hidden: true;
// this route cannot be clicked in breadcrumb navigation when noredirect is set
redirect: noredirect;
// when you route a children below the declaration of more than one route,
// it will automatically become a nested mode - such as the component page
// when there is only one, the child route will be displayed as the root route
// if you want to display your root route
// regardless of the number of children declarations under the route
// you can set alwaysShow: true
// so that it will ignore the previously defined rules and always show the root route
alwaysShow: true;
// set router name. It must be setted,in order to avoid problems with <keep-alive>.
name: "router-name";
meta: {
// required roles to navigate to this route. Support multiple permissions stacking.
// if not set means it doesn't need any permission.
roles: ["admin", "editor"];
// the title of the route to show in various components (e.g. sidebar, breadcrumbs).
title: "title";
// svg icon class
icon: "svg-name";
// when set true, the route will not be cached by <keep-alive>. Default false
noCache: true;
}
Example:
{
path: '/permission',
component: Layout,
redirect: '/permission/index',
hidden: true,
alwaysShow: true,
meta: { roles: ['admin','ediotr'] }, // you can set roles in root nav
children: [{
path: 'index',
component: _import('permission/index'),
name: 'permission',
meta: {
title: 'permission',
icon: 'lock',
roles: ['admin','ediotr'], // or you can only set roles in sub nav
noCache: true
}
}]
}
Router
There are two types of routes here , constantRouterMap
and asyncRouterMap
.
constantRouterMap: represents routes that do not require dynamic access, such as login page, 404, general page, and so on.
asyncRouterMap: represents pages that require dynamic judgment permissions and are dynamically added through addRouters
. The details will be introduced on the permission.
TIP
All routing pages here use the router lazy loading
, as described in document
If you want to know more about browserHistory and hashHistory, please refer to Build & Deploy.
The other configurations are no different from the vue-router official, so check the documentation for yourself.
WARNING
There is one thing to be careful about is that the 404 page must be the last to load, if it is declared in constantRouterMap. Later declared pages will be blocked to 404, see the details of the problem: addRoutes when you've got a wildcard route for 404s does not work
Sidebar
The project sidebar is mainly based on the el-menu
of element-ui.
Also introduced in the front, the sidebar is generated dynamically by reading the route and combined with the permission judge, but also need to support the infinite nesting of routes, so here is also used to the recursive components.
This also modify many default sidebar styles of element-ui
. All css can be found in @/styles/sidebar.scss and can be modified to suit your needs.
Here need to pay attention. The general sidebar has two forms, submenu
andel-menu-item
. One is a nested submenu, the other is a direct link. As shown below:
The sidebar has already helped you to make a judgment. When you route a children below the declaration of more than >1 routes, it will automatically become a nested mode. If the sub-route is exactly equal to one, the sub-route is displayed as a root route in the sidebar by default. If you do not want to, you can disable this feature by setting alwaysShow: true
in the root route. Such as:
// no submenu, because children.length===1
{
path: '/icon',
component: Layout,
children: [{
path: 'index',
component: ()=>import('svg-icons/index'),
name: 'icons',
meta: { title: 'icons', icon: 'icon'}
}]
},
// has submenu, because children.length>=1
{
path: '/components',
component: Layout,
name: 'component-demo',
meta: {
title: 'components',
icon: 'component'
},
children: [
{ path: 'tinymce', component: ()=>import('components-demo/tinymce'), name: 'tinymce-demo', meta: { title: 'tinymce' }},
{ path: 'markdown', component: ()=>import('components-demo/markdown'), name: 'markdown-demo', meta: { title: 'markdown' }},
]
}
Click the sidebar to refresh the current route
Before using the development model of spa(single page application), each time the user clicks the sidebar will request this page again, the user gradually developed the habit of clicking the current route in the sidebar to refresh the view. But now the spa is not the same, the user clicks the currently highlighted route and does not refresh the view, because the vue-router will intercept your routing, it determines your url does not change, so it will not trigger any hook or view changes.Related issue, the community has also heated discussions on the issue.
yyx990803
also said that he wanted to add a way to brighten the view, but later he changed his mind again/(ㄒ o ㄒ)/~~ But demand is here, what should we do? He said it would not trigger anything without changing the current URL, so can I force the trigger? The hack is simple. By changing the url query to trigger the view changes。We listen to each link's click event on the sidebar, each click will push a different query for the router to ensure that the view is refreshed.
clickLink(path) {
this.$router.push({
path,
query: {
//Ensure that each click, query is not the same
//to ensure that refresh the view
t: +new Date()
}
})
}
ps: Don't forget to add a unique key
to router-view
, such as <router-view :key="$route.path"></router-view>
.
But there's also a drawback the ugly query
suffix behind url, such as xxx.com/article/list?t=1496832345025
You can know from the previous issue that there are many other options. In my company project, the solution adopted is to determine whether the currently clicked menu route is consistent with the current route. However, when it is consistent, it will jump to a dedicated Redirect page, which will redirect the route to Go to the page, this will have a refresh effect.
Breadcrumb
This project also packages a breadcrumb navigation, which is also dynamically generated by the watch $route change. It is the same with the menu, you can also config it in the routing. You can also add some custom attributes to your business needs in route.meta attr.
Corresponding code: @/components/Breadcrumb
Sidebar scroll problem
Previous versions of scroll were handled with css
overflow-y: scroll;
::-webkit-scrollbar {
display: none;
}
But hack by css has some problems, in Firefox or other lower versions of the browser will be less beautiful.
Second, in the case of sidebar collapses, limited to menu
ofelement-ui
, can not be handled in this way.
So the current version uses el-scrollbar
to handle the sidebar scrolling problem.