vue-element-admin
vue-element-admin copied to clipboard
在 keep-alive 下嵌套多级 router-view,在 include 属性的约束下,缓存失效
在 keep-alive 下嵌套多级 router-view,在 include 属性的约束下,缓存失效
Other relevant information(格外信息)
- Node.js version: v12.3.0
- vue-element-admin version: v3.11.0
路由name跟组件name要一样是不是这个问题或者没设置
去掉include虽然可以缓存了,但是有很多问题,所有在tagviews上的组件会重新渲染
路由name跟组件name要一样是不是这个问题或者没设置
我也遇到和楼主一样的问题,打印过路由name和组件name一样的,同样在多级下失效,若楼主解决麻烦指点下哦,谢谢
我也遇到相同的问题,多级组件下,未缓存父级组件,导致子组件未缓存。
感觉应该要在父级的
我把父级组件的name直接写进了cacheViews数组里面,虽然可以缓存子组件,但是导致子组件关闭后还一直在缓存,不知道该怎么办
我也遇到了相同的问题,去掉include就可以了
我是也是遇到这个问题,有解决方案没?
root-view嵌套导致的。正常一级菜单下只有二级菜单是没问题的,但是有三级菜单就会出现
经过各种方式的尝试,发现将路由全部转成二级菜单应该是比较不错的处理方式(其它方式多多少少均有一些比较明显的问题)
具体操作如下
- 克隆原路由数组(克隆时将component字段除外,也就是component不进行克隆)
- 对克隆后的路由数组进行降级处理,动态添加到router中,原路由数组可用来做侧边栏菜单的展示(菜单和路由分离)
- 路由降级后,会对面包屑菜单产生影响(展示时中间少了一些层级),可以手动处理还原展示
经过各种方式的尝试,发现将路由全部转成二级菜单应该是比较不错的处理方式(其它方式多多少少均有一些比较明显的问题)
具体操作如下
- 克隆原路由数组(克隆时将component字段除外,也就是component不进行克隆)
- 对克隆后的路由数组进行降级处理,动态添加到router中,原路由数组可用来做侧边栏菜单的展示(菜单和路由分离)
- 路由降级后,会对面包屑菜单产生影响(展示时中间少了一些层级),可以手动处理还原展示
请教下,能否让我看下你那边的处理代码呢
经过各种方式的尝试,发现将路由全部转成二级菜单应该是比较不错的处理方式(其它方式多多少少均有一些比较明显的问题)
具体操作如下
- 克隆原路由数组(克隆时将component字段除外,也就是component不进行克隆)
- 对克隆后的路由数组进行降级处理,动态添加到router中,原路由数组可用来做侧边栏菜单的展示(菜单和路由分离)
- 路由降级后,会对面包屑菜单产生影响(展示时中间少了一些层级),可以手动处理还原展示
请教下,能否让我看下你那边的处理代码呢
我把改动的地方都截取出来了,你放到自己的代码中看看
写的比较匆忙,处理方式应该还可以优化,你自己再改改
// 原路由
const asyncRoutes = [...]
// 降级后的路由
const flatRoutes = getFlatRoutes(deepClone(asyncRoutes, ['component']))
// 几个用到的方法
// 二级以上的菜单降级成二级菜单
const formatRouter = (routes, basePath = '/', list = [], parent) => {
routes.map(item => {
item.path = path.resolve(basePath, item.path)
const meta = item.meta || {}
if (!meta.parent && parent) {
meta.parent = parent.path
item.meta = meta
}
if (item.redirect) item.redirect = path.resolve(basePath, item.redirect)
if (item.children && item.children.length > 0) {
const arr = formatRouter(item.children, item.path, list, item)
delete item.children
list.concat(arr)
}
list.push(item)
})
return list
}
// 菜单降级
export const getFlatRoutes = (routes) => {
return routes.map((child) => {
if (child.children && child.children.length > 0) {
child.children = formatRouter(child.children, child.path, [], child)
}
return child
})
}
// Breadcrumb/index.vue (面包屑处理)
...
// let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
let matched = this.getBreadcrumbRoutes().filter(item => item.meta && item.meta.title)
....
getBreadcrumbRoutes () {
let currentRoutes = {}
const first = this.$route.matched[0]
let last = this.$route.matched[this.$route.matched.length - 1]
const matched = []
// 倒序遍历有meta.parent标识的路由
for (let i = this.$route.matched.length - 1; i >= 0; i--) {
const match = this.$route.matched[i]
const meta = match.meta || {}
matched.unshift(match)
if (meta.parent) {
last = match
break
}
}
// 填充降级后缺失的各级路由
this.flatRoutes.some(item => {
if (item.path === first.path) {
currentRoutes = item.children
this.getParentRoute(currentRoutes, last, matched)
return true
}
})
matched.unshift(first)
return matched
},
getParentRoute (currentRoutes, last, matched = []) {
const meta = last.meta || {}
currentRoutes.forEach((item) => {
if (item.path === meta.parent) {
matched.unshift(item)
this.getParentRoute(currentRoutes, item, matched)
}
})
return matched
}
经过各种方式的尝试,发现将路由全部转成二级菜单应该是比较不错的处理方式(其它方式多多少少均有一些比较明显的问题)
具体操作如下
- 克隆原路由数组(克隆时将component字段除外,也就是component不进行克隆)
- 对克隆后的路由数组进行降级处理,动态添加到router中,原路由数组可用来做侧边栏菜单的展示(菜单和路由分离)
- 路由降级后,会对面包屑菜单产生影响(展示时中间少了一些层级),可以手动处理还原展示
请教下,能否让我看下你那边的处理代码呢
我把改动的地方都截取出来了,你放到自己的代码中看看
写的比较匆忙,处理方式应该还可以优化,你自己再改改
// 原路由 const asyncRoutes = [...] // 降级后的路由 const flatRoutes = getFlatRoutes(deepClone(asyncRoutes, ['component'])) // 几个用到的方法 // 二级以上的菜单降级成二级菜单 const formatRouter = (routes, basePath = '/', list = [], parent) => { routes.map(item => { item.path = path.resolve(basePath, item.path) const meta = item.meta || {} if (!meta.parent && parent) { meta.parent = parent.path item.meta = meta } if (item.redirect) item.redirect = path.resolve(basePath, item.redirect) if (item.children && item.children.length > 0) { const arr = formatRouter(item.children, item.path, list, item) delete item.children list.concat(arr) } list.push(item) }) return list } // 菜单降级 export const getFlatRoutes = (routes) => { return routes.map((child) => { if (child.children && child.children.length > 0) { child.children = formatRouter(child.children, child.path, [], child) } return child }) }
// Breadcrumb/index.vue (面包屑处理) ... // let matched = this.$route.matched.filter(item => item.meta && item.meta.title) let matched = this.getBreadcrumbRoutes().filter(item => item.meta && item.meta.title) .... getBreadcrumbRoutes () { let currentRoutes = {} const first = this.$route.matched[0] let last = this.$route.matched[this.$route.matched.length - 1] const matched = [] // 倒序遍历有meta.parent标识的路由 for (let i = this.$route.matched.length - 1; i >= 0; i--) { const match = this.$route.matched[i] const meta = match.meta || {} matched.unshift(match) if (meta.parent) { last = match break } } // 填充降级后缺失的各级路由 this.flatRoutes.some(item => { if (item.path === first.path) { currentRoutes = item.children this.getParentRoute(currentRoutes, last, matched) return true } }) matched.unshift(first) return matched }, getParentRoute (currentRoutes, last, matched = []) { const meta = last.meta || {} currentRoutes.forEach((item) => { if (item.path === meta.parent) { matched.unshift(item) this.getParentRoute(currentRoutes, item, matched) } }) return matched }
好的,谢谢,我这里研究一下看看。
经过各种方式的尝试,发现将路由全部转成二级菜单应该是比较不错的处理方式(其它方式多多少少均有一些比较明显的问题)
具体操作如下
- 克隆原路由数组(克隆时将component字段除外,也就是component不进行克隆)
- 对克隆后的路由数组进行降级处理,动态添加到router中,原路由数组可用来做侧边栏菜单的展示(菜单和路由分离)
- 路由降级后,会对面包屑菜单产生影响(展示时中间少了一些层级),可以手动处理还原展示
请教下,能否让我看下你那边的处理代码呢
我把改动的地方都截取出来了,你放到自己的代码中看看
写的比较匆忙,处理方式应该还可以优化,你自己再改改
// 原路由 const asyncRoutes = [...] // 降级后的路由 const flatRoutes = getFlatRoutes(deepClone(asyncRoutes, ['component'])) // 几个用到的方法 // 二级以上的菜单降级成二级菜单 const formatRouter = (routes, basePath = '/', list = [], parent) => { routes.map(item => { item.path = path.resolve(basePath, item.path) const meta = item.meta || {} if (!meta.parent && parent) { meta.parent = parent.path item.meta = meta } if (item.redirect) item.redirect = path.resolve(basePath, item.redirect) if (item.children && item.children.length > 0) { const arr = formatRouter(item.children, item.path, list, item) delete item.children list.concat(arr) } list.push(item) }) return list } // 菜单降级 export const getFlatRoutes = (routes) => { return routes.map((child) => { if (child.children && child.children.length > 0) { child.children = formatRouter(child.children, child.path, [], child) } return child }) }
// Breadcrumb/index.vue (面包屑处理) ... // let matched = this.$route.matched.filter(item => item.meta && item.meta.title) let matched = this.getBreadcrumbRoutes().filter(item => item.meta && item.meta.title) .... getBreadcrumbRoutes () { let currentRoutes = {} const first = this.$route.matched[0] let last = this.$route.matched[this.$route.matched.length - 1] const matched = [] // 倒序遍历有meta.parent标识的路由 for (let i = this.$route.matched.length - 1; i >= 0; i--) { const match = this.$route.matched[i] const meta = match.meta || {} matched.unshift(match) if (meta.parent) { last = match break } } // 填充降级后缺失的各级路由 this.flatRoutes.some(item => { if (item.path === first.path) { currentRoutes = item.children this.getParentRoute(currentRoutes, last, matched) return true } }) matched.unshift(first) return matched }, getParentRoute (currentRoutes, last, matched = []) { const meta = last.meta || {} currentRoutes.forEach((item) => { if (item.path === meta.parent) { matched.unshift(item) this.getParentRoute(currentRoutes, item, matched) } }) return matched }
好的,谢谢,我这里研究一下看看。
path.resolve(basePath, item.path) 这path是哪的。。。
@zzc69 import path from 'path'
经过各种方式的尝试,发现将路由全部转成二级菜单应该是比较不错的处理方式(其它方式多多少少均有一些比较明显的问题)
具体操作如下
- 克隆原路由数组(克隆时将component字段除外,也就是component不进行克隆)
- 对克隆后的路由数组进行降级处理,动态添加到router中,原路由数组可用来做侧边栏菜单的展示(菜单和路由分离)
- 路由降级后,会对面包屑菜单产生影响(展示时中间少了一些层级),可以手动处理还原展示
请教下,能否让我看下你那边的处理代码呢
我把改动的地方都截取出来了,你放到自己的代码中看看
写的比较匆忙,处理方式应该还可以优化,你自己再改改
// 原路由 const asyncRoutes = [...] // 降级后的路由 const flatRoutes = getFlatRoutes(deepClone(asyncRoutes, ['component'])) // 几个用到的方法 // 二级以上的菜单降级成二级菜单 const formatRouter = (routes, basePath = '/', list = [], parent) => { routes.map(item => { item.path = path.resolve(basePath, item.path) const meta = item.meta || {} if (!meta.parent && parent) { meta.parent = parent.path item.meta = meta } if (item.redirect) item.redirect = path.resolve(basePath, item.redirect) if (item.children && item.children.length > 0) { const arr = formatRouter(item.children, item.path, list, item) delete item.children list.concat(arr) } list.push(item) }) return list } // 菜单降级 export const getFlatRoutes = (routes) => { return routes.map((child) => { if (child.children && child.children.length > 0) { child.children = formatRouter(child.children, child.path, [], child) } return child }) }
// Breadcrumb/index.vue (面包屑处理) ... // let matched = this.$route.matched.filter(item => item.meta && item.meta.title) let matched = this.getBreadcrumbRoutes().filter(item => item.meta && item.meta.title) .... getBreadcrumbRoutes () { let currentRoutes = {} const first = this.$route.matched[0] let last = this.$route.matched[this.$route.matched.length - 1] const matched = [] // 倒序遍历有meta.parent标识的路由 for (let i = this.$route.matched.length - 1; i >= 0; i--) { const match = this.$route.matched[i] const meta = match.meta || {} matched.unshift(match) if (meta.parent) { last = match break } } // 填充降级后缺失的各级路由 this.flatRoutes.some(item => { if (item.path === first.path) { currentRoutes = item.children this.getParentRoute(currentRoutes, last, matched) return true } }) matched.unshift(first) return matched }, getParentRoute (currentRoutes, last, matched = []) { const meta = last.meta || {} currentRoutes.forEach((item) => { if (item.path === meta.parent) { matched.unshift(item) this.getParentRoute(currentRoutes, item, matched) } }) return matched }
能否分享一下这个deepClone(asyncRoutes, ['component']) 实现方法
能否分享一下这个deepClone(asyncRoutes, ['component']) 实现方法
作者的意思就是把component这个key复制时忽略,改写一下deepClone /**
- @param {Object} source
- @param {Array} ignore
- @returns {Object} */
export function deepClone(source,ignore) {
if (!source && typeof source !== 'object') {
throw new Error('error arguments', 'deepClone');
}
const targetObj = source.constructor === Array ? [] : {};
Object.keys(source).forEach(keys => {
if (!ignore.includes(keys)) {
if (source[keys] && typeof source[keys] === 'object') {
targetObj[keys] = deepClone(source[keys],ignore);
} else {
targetObj[keys] = source[keys];
}
}
});
return targetObj;
}
最好的方式可以将三级或者更多的菜单拍平,菜单的渲染结果默认为后端返回渲染,但是实际生成的路由结果要拍平为二位数组的嵌套结构,改动最少,效果也最好
能否分享一下这个deepClone(asyncRoutes, ['component']) 实现方法
作者的意思就是把component这个key复制时忽略,改写一下deepClone /**
- @param {Object} source
- @param {Array} ignore
- @returns {Object} */
export function deepClone(source,ignore) { if (!source && typeof source !== 'object') { throw new Error('error arguments', 'deepClone'); } const targetObj = source.constructor === Array ? [] : {}; Object.keys(source).forEach(keys => { if (!ignore.includes(keys)) { if (source[keys] && typeof source[keys] === 'object') { targetObj[keys] = deepClone(source[keys],ignore); } else { targetObj[keys] = source[keys]; } } }); return targetObj; }
应该是浅拷贝component而不是完全不拷贝吧