目的:为了每次跳转特定的路由后,返回时不会清空缓存,多用于翻页后的点击跳转。
参考官方文档:https://cn.vuejs.org/v2/api/#keep-alive
具体实现
1、路由修改
src--router--index.js
meta: {
activeMenu: '/deviceManagement/monitoringDevice',//详情页
keepAlive: true,
keepAliveName: ['monitoringDevice','equipmentDetail']//组件的名字也要修改
},
meta: {
keepAlive: true,//跳转页
keepAliveName: ['monitoringDevice']
}
2、三级路由改二级
store--modules--permisstion.js
import { routesMap, constantRoutes } from '@/router'
/**
* Use meta.role to determine if the current user has permission
* @param roles
* @param route
*/
// function hasPermission(roles, route) {
// if (route.meta && route.meta.roles) {
// return roles.some(role => route.meta.roles.includes(role))
// } else {
// return true
// }
// }
/**
* Filter asynchronous routing by recursion
* @param routes asyncRoutes
* @param menu
*/
export function filterAsyncRoutes(routeMap, menu) {
const res = []
menu.forEach(item => {
// if (item.type === 1 || item.type === 4 || item.type === 3) {
let route = { ...item, hidden: false }
route.component = routeMap[item.url]
? routeMap[item.url]['component']
: null
route.name = routeMap[item.url] ? routeMap[item.url]['name'] : ''
route.redirect = route['redirect'] !== '#' ? item['redirect'] : ''
// route.hidden = routeMap[item.url] ? routeMap[item.url]['hidden'] : false
route.hidden = item.type !== 1 && item.type !== 4
route.meta = {
title: item.title,
icon: item.icon,
type: item.type,
keepAlive: false
}
if (routeMap[item.url]) {
if (routeMap[item.url]['meta']) {
if (routeMap[item.url]['meta'].activeMenu) {
route.meta['activeMenu'] = routeMap[item.url]['meta'].activeMenu
}
if (routeMap[item.url]['meta'].keepAlive) {
route.meta['keepAlive'] = routeMap[item.url]['meta'].keepAlive
}
if (routeMap[item.url]['meta'].keepAliveName) {
route.meta['keepAliveName'] =
routeMap[item.url]['meta'].keepAliveName
}
// console.log("routeMap", routeMap[item.url]);
}
}
if (route.children) {
route.children = filterAsyncRoutes(routeMap, item.children)
}
res.push(route)
})
return res
}
// 根据pid创建子菜单
function getChildren(nodeList, jsonData) {
let menus = nodeList
menus.forEach(element => {
element.children = jsonData.filter(item => {
return item.pid === element.id
})
if (element.children.length > 0) {
element.children=getNew(element.children,jsonData)//三级路由
element.children=getNew(element.children,jsonData)//四级路由
element.children=getNew(element.children,jsonData)//五级路由 目前没有
element.children=getNew(element.children,jsonData)//六级路由 目前没有
element.children=repeat(element.children)
} else {
delete element.children
}
})
return menus
}
function getNew(children,jsonData){
let myChildren=children
myChildren.forEach(element2 => {
let a = jsonData.filter(item => {
return item.pid === element2.id
})
myChildren=myChildren.concat(a)
// console.log('新的数组',myChildren);
})
return myChildren
}
//去重
function repeat(arr) {
if (!Array.isArray(arr)) {
console.log('type error!')
return
}
var array = [];
for (var i = 0; i < arr.length; i++) {
if (array.indexOf(arr[i]) === -1) {
array.push(arr[i])
}
}
return array;
}
// 根据pid创建菜单
export function createMenu(jsonData) {
let resultObj = []
let baseNode = jsonData.filter(element => {
return element.pid === 0
})
resultObj.push(...baseNode)
return getChildren(resultObj, jsonData)
}
const state = {
routes: [],
addRoutes: [],
catchcomponents: []
}
const mutations = {
SET_ROUTES: (state, routes) => {
state.addRoutes = routes
state.routes = constantRoutes.concat(routes)
},
GET_CATCHE_COMPONENTS(state, data) {
state.catchcomponents = data
}
}
const actions = {
generateRoutes({ commit }, menu) {
return new Promise(resolve => {
const accessedRoutes = filterAsyncRoutes(routesMap, createMenu(menu))
commit('SET_ROUTES', accessedRoutes)
resolve(accessedRoutes)
})
},
changecomponents({ commit }, data) {
commit('GET_CATCHE_COMPONENTS', data)
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
3、路由拦截
src---permission
if (hasRoles) {
// 去往详情页的时候需要缓存组件,其他情况下不需要缓存 --->(需要提前加入缓存,因为第一次加入的数据是之前的)
console.log('是否需要缓存:' + to.meta.keepAlive, to, to.meta.title)
if (to.meta.keepAlive) {
store.dispatch('permission/changecomponents',
to.meta.keepAliveName
)
} else if (!to.meta.keepAlive) {
store.dispatch('permission/changecomponents', [])
}
console.log('加入的数组', store.state.permission.catchcomponents)
next()
}
4、面包屑
components--Breadcrumb
<template>
<el-breadcrumb class="app-breadcrumb" separator=">">
<transition-group name="breadcrumb">
<el-breadcrumb-item v-for="(item, index) in levelList" :key="item.path">
<span
v-if="item.redirect === 'noRedirect' || index == levelList.length - 1"
class="no-redirect"
>
{{
generateTitle(item.meta.title)
}}
</span>
<a v-else @click.prevent="handleLink(item)">{{ generateTitle(item.meta.title) }}</a>
</el-breadcrumb-item>
</transition-group>
</el-breadcrumb>
</template>
<script>
import pathToRegexp from 'path-to-regexp'
import { generateTitle } from '@/utils/i18n'
export default {
data() {
return {
levelList: null
}
},
watch: {
$route(after, before) {
this.getBreadcrumb(after, before)
}
},
created() {
this.getBreadcrumb()
},
methods: {
// 更新密码
changePsd() {
this.$refs.changePassword.update()
},
generateTitle,
getRepeat(matched, menu, pid) {
let myMatched = matched
menu.map((item) => {
if (item.id === pid) {
console.log('寻找***', item.name)
myMatched.splice(1, 0, item)
this.getRepeat(myMatched, menu, item.pid)
}
})
return myMatched
},
getBreadcrumb(after, before) {
// only show routes with meta.title
// console.log('this.$route', this.$route, this.$router)
let matched = this.$route.matched.filter((item) => item.meta && item.meta.title)
let allrouter = this.$router.options.routes.filter((item) => item.meta && item.meta.title)
// console.log('matched', matched, allrouter)
let first = matched[0]
let second = matched[1]
allrouter.map((item) => {
if (first.name === item.name) {
item.children.map((item2) => {
if (item2.name === second.name) {
// console.log('寻找二', item2.name)
this.getRepeat(matched, item.children, item2.pid)
}
})
}
})
// console.log('first', first)
if (!this.isDashboard(first)) {
matched = [].concat(matched)
// console.log('判断后的matched', matched)
}
this.levelList = matched.filter((item) => item.meta && item.meta.title && item.meta.breadcrumb !== false)
// console.log('集合', this.levelList)
},
isDashboard(route) {
const name = route && route.name
if (!name) {
return false
}
// console.log('name', name.trim().toLocaleLowerCase(), 'Dashboard'.toLocaleLowerCase())
return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()
},
pathCompile(path) {
// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
const { params } = this.$route
console.log('this.$route',this.$route);
let toPath = pathToRegexp.compile(path)
// console.log('toPath',toPath);
return toPath(params)
},
handleLink(item) {
console.log('item',item);
const { redirect, path } = item
if (redirect) {
this.$router.push(redirect)
return
}
this.$router.push(this.pathCompile(path))
}
}
}
</script>
<style lang="scss" scoped>
.app-breadcrumb.el-breadcrumb {
display: inline-block;
font-size: 15px;
line-height: 60px;
margin-left: 8px;
.no-redirect {
color: #97a8be;
cursor: text;
}
}
</style>
5、页面进入缓存事件
deviceManagement--euqipment--detail--index.vue
//页面缓存会进入此周期
activated() {
console.log('keepAlive+++执行', this.id)
if (this.$route.name === 'equipmentDetail') {
this.$store.dispatch('app/setReqId', this.id)//恢复本地存储
console.log(this.id)
}
},