Refer to the project github address vue-element-admin official github.com/PanJiaChen/… AdminLTE (nice style library) github.com/ColorlibHQ/…
Project initialization
Use vuE-CLI3 to initialize the visual project, referBlog.csdn.net/qq_40636998…
catalogue
Permissions routing
Permission routing is mainly used for permission authentication. Different roles enter the system and present different menus and routes. Most permission routing is conducted by setting the route interceptor in the router beforeEach to determine whether the Cookie or Session already has the Token for login authentication. If yes, go to the next step to obtain routing information from the backend. If no, the login page is displayed. It should be noted that the user’s information and routes are stored in VUEX. In this way, when the page is refreshed, the user’s information or permission is changed on the other end, so that the function can update the information in time. Menus and routes are stored and refreshed in VUEX.
router.beforeEach((to, from, next) = > {
const token = store.state.user.token || ' ';
if (token) { // Check whether there is a token
if (to.path === '/userlogin/login') {// Determine whether to redirect to the login page. If there is a token, reset the login page request directly to the home page
next({
path: '/'
});
} else {
if (store.getters.username.length === 0) { // Check whether the current user has finished fetching user_info (user information is stored in vuex)
store.dispatch('user/GetInfo').then(() = > { // Pull user information
store.dispatch('permission/GenerateRoutes').then(() = > { // Generate an accessible routing table
router.addRoutes(store.getters.addRouters) // Dynamically add accessible routing table (obtained from vuEX)next({ ... to,replace: true
}) // the hack method ensures that addRoutes is complete,set the replace: true so the navigation will not leave a history record
})
}).catch(err= > {
console.log(err);
});
} else {
next() // If the user has permission, all accessible routes have been generated. If the user does not have permission to access all routes, the 404 page will be displayed automatically}}}else {
if (to.path.includes('/userlogin')) {
next();
} else {
next('/userlogin'); // Otherwise all redirects to the login page}}});Copy the code
In dynamic routing, we need to configure two routes, static and dynamic, in the router. Static route is the default route loaded by the project, and dynamic route is used to splice the route data returned by the interface.
export const constantRouterMap = [// Static routes are loaded by default
{
path: '/redirect'.component: Layout,
hidden: true.children: [{path: '/redirect/:path*'.component: () = >
import( /* webpackChunkName: "redirect" */ '@/views/redirect/index'),}]}, {path: "/userlogin".name: "userlogin".redirect: "/userlogin/login".hidden: true.component: () = >
import( /* webpackChunkName: "layout" */ "@/layout/user/userlayout.vue"),
children: [{
path: "/userlogin/login".name: "login".hidden: true.component: () = >
import( /* webpackChunkName: "login" */ "@/views/user/login.vue")}, {path: "/userlogin/register".name: "register".hidden: true.component: () = >
import( /* webpackChunkName: "register" */ "@/views/user/register.vue"}]}];export const asyncRouterMap = [// Dynamic routing is used for later stitching
{
path: '/'.name: 'home'.redirect: '/home/main'.component: Layout,
children: [{
path: '/home/main'.name: 'mainhome'.meta: {title: 'home'
},
component: () = >
import( /* webpackChunkName: "main" */ "@/views/Home.vue")}}]];Copy the code
Keep-alive multi-level cache
Multi-level caching is very common in background projects. It is mostly used in the navigation bar at the top, and special processing is required when the routing level is 3
Keep-alive wraps are performed on the router-view that needs to be cached. CachedView is the route name that needs to be cached
<template>
<keep-alive :include="cachedViews">
<router-view :key="key"></router-view>
</keep-alive>
</template>
<script>
computed: {
cachedViews() {
return this.$store.state.tagsView.cachedViews; }},</script>
Copy the code
The page that vuEX squadron needs to cache is stored, and multi-level routes need to add the parent route to the cachedViews cache, otherwise the cache cannot succeed, and every VUE page needs to add the attribute name:”” to identify the page that needs to be cached. In the clear cache, you need to clear the name of the parent page from the cache, otherwise the page will still be cached.
const state = {
visitedViews: [].cachedViews: [].cachedViewsParent: []// Store the parent information of each route
}
const mutations = {
ADD_VISITED_VIEW: (state, view) = > {
if (state.visitedViews.some(v= > v.path === view.path)) return
state.visitedViews.push(
Object.assign({}, view, {
title: view.meta.title || 'no-name'}})),ADD_CACHED_VIEW: (state, view) = > {
// Multilevel cache
if (state.cachedViews.includes(view.name)) return
view.matched.map(item= > {
// Do not cache the home page
if (item.name.indexOf('home') = = -1 && state.cachedViews.indexOf(item.name) == -1) {
state.cachedViews.push(item.name)
}
});
// Do not cache the home page
if(! view.name.includes('home')) {
state.cachedViewsParent.push({
name: view.name,
parent: view.matched.filter(item= > item.name.indexOf('home') = = -1).map(item= >item.name) }); }},DEL_VISITED_VIEW: (state, view) = > {
for (const [i, v] of state.visitedViews.entries()) {
if (v.path === view.path) {
state.visitedViews.splice(i, 1)
break}}},DEL_CACHED_VIEW: (state, view) = > {
let arr = [];
state.cachedViewsParent = state.cachedViewsParent.filter(item= >item.name ! = view.name);// Do not delete the upper-level route at the same level
state.cachedViewsParent.map(i= > [
arr.push(...i.parent)
]);
view.matched.map(item= > {
if(! arr.includes(item.name)) {const index = state.cachedViews.indexOf(item.name)
index > -1 && state.cachedViews.splice(index, 1)}})},DEL_OTHERS_VISITED_VIEWS: (state, view) = > {
state.visitedViews = state.visitedViews.filter(v= > {
return v.meta.affix || v.path === view.path
})
},
DEL_OTHERS_CACHED_VIEWS: (state, view) = > {
const index = state.cachedViews.indexOf(view.name)
if (index > -1) {
state.cachedViews = state.cachedViews.slice(index, index + 1)}else {
// if index = -1, there is no cached tags
state.cachedViews = []
}
},
DEL_ALL_VISITED_VIEWS: state= > {
// keep affix tags
const affixTags = state.visitedViews.filter(tag= > tag.meta.affix)
state.visitedViews = affixTags
},
DEL_ALL_CACHED_VIEWS: state= > {
state.cachedViews = []
},
UPDATE_VISITED_VIEW: (state, view) = > {
for (let v of state.visitedViews) {
if (v.path === view.path) {
v = Object.assign(v, view)
break}}}}const actions = {
addView({ dispatch }, view) {
dispatch('addVisitedView', view)
dispatch('addCachedView', view)
},
addVisitedView({ commit }, view) {
commit('ADD_VISITED_VIEW', view)
},
addCachedView({ commit }, view) {
commit('ADD_CACHED_VIEW', view)
},
delView({ dispatch, state }, view) {
return new Promise(resolve= > {
dispatch('delVisitedView', view)
dispatch('delCachedView', view)
resolve({
visitedViews: [...state.visitedViews],
cachedViews: [...state.cachedViews]
})
})
},
delVisitedView({ commit, state }, view) {
return new Promise(resolve= > {
commit('DEL_VISITED_VIEW', view)
resolve([...state.visitedViews])
})
},
delCachedView({ commit, state }, view) {
return new Promise(resolve= > {
commit('DEL_CACHED_VIEW', view)
resolve([...state.cachedViews])
})
},
delOthersViews({ dispatch, state }, view) {
return new Promise(resolve= > {
dispatch('delOthersVisitedViews', view)
dispatch('delOthersCachedViews', view)
resolve({
visitedViews: [...state.visitedViews],
cachedViews: [...state.cachedViews]
})
})
},
delOthersVisitedViews({ commit, state }, view) {
return new Promise(resolve= > {
commit('DEL_OTHERS_VISITED_VIEWS', view)
resolve([...state.visitedViews])
})
},
delOthersCachedViews({ commit, state }, view) {
return new Promise(resolve= > {
commit('DEL_OTHERS_CACHED_VIEWS', view)
resolve([...state.cachedViews])
})
},
delAllViews({ dispatch, state }, view) {
return new Promise(resolve= > {
dispatch('delAllVisitedViews', view)
dispatch('delAllCachedViews', view)
resolve({
visitedViews: [...state.visitedViews],
cachedViews: [...state.cachedViews]
})
})
},
delAllVisitedViews({ commit, state }) {
return new Promise(resolve= > {
commit('DEL_ALL_VISITED_VIEWS')
resolve([...state.visitedViews])
})
},
delAllCachedViews({ commit, state }) {
return new Promise(resolve= > {
commit('DEL_ALL_CACHED_VIEWS')
resolve([...state.cachedViews])
})
},
updateVisitedView({ commit }, view) {
commit('UPDATE_VISITED_VIEW', view)
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
Copy the code
Multilevel routing cache will appear pit, of course, at the same time open multiple routing of the same parent page, close to remove page cannot successfully remove the routing cache, the multilevel routing filter replaced with two stage routing, specific can consult the solution segmentfault.com/a/119000003…
let allChildren = [];
// Convert multi-level routes to level-2 routes for keep-alive(find all leaf nodes, expand flat)
export const flatAsyncRouter = (routers) = > {
searchchildren(routers)
return allChildren;
}
let searchchildren = (arr) = > {
arr.map(item= > {
if (item.children && item.children.length > 0) {
searchchildren(item.children)
} else {
allChildren.push(item)
}
})
}
Copy the code