1. 为什么三级会缓存不了
在src/layout/AppMain组件:
在这里插入图片描述
keep-alive的组件依赖cachedViews,cachedViews是store中的一个状态,
cachedViews的逻辑在src/layout/TagView
在这里插入图片描述
当路由变更时就会调用addViewTags,addViewTag会根据匹配的路由name属性进行缓存。而用到三级路由的时候,拿到name只能时第三级路由的name,二级路由组件的名字会丢失,keep-alive就不会进行缓存。
知道原因之后,第一个想法就是把二级路由的name也加上去就好了。要实现这个也很简单,只需要获取到matched属性就可以拿到匹配到的路由组件,把它加入到cachedViews数组就好了。但是有个问题就是,假设这里有个二级路由1-1,三级路由1-1-1,1-1-2,当要关掉1-1-1组件时,你到底要不要把1-1给删了,如果删了,缓存能顺利失效,但是如果你之前是打开了1-1-2,缓存的路由就会失效,因为它是依赖1-1的。如果不删的话,在侧边栏打开1-1-1的链接的时候,它又会重新复用回原本的组件。

3. 把三级(概念上的)转化为二级(真实)
在这里想来,如果1-1-1,1-1-2,其实只是因为分在同类别里,两者如果没有实际共享的数据,那可以考虑把1-1的路由组件关掉,在我实践的项目就是如此,1-1-1和1-1-2只是同属在二级菜单下,并没有共享数据。但是生成菜单的时候是用router表的,那么生成菜单的用原本的,生成路由的时候用替换的。

下面是demo代码:
将要被替换的路由加上noCompoent属性。

function delteFakeParent(router,prefix) {
    var newRouter = { ...router }
    if(prefix){
        newRouter.path = prefix + '/' + router.path
    }
    if (!router.children) return newRouter
    var children = []
    if (router.noCompoent) {
        for (let i = 0; i < router.children.length; i++) {
            const item = delteFakeParent(router.children[i], newRouter.path)
            if (Array.isArray(item)) {
                item.forEach(el => {
                    children.push(el)
                })
            }else{
                children.push(item)
            }
        }
        newRouter = children
    } else {
        for (let i = 0; i < router.children.length; i++) {
            const item = delteFakeParent(router.children[i])
            if (Array.isArray(item)) {
                item.forEach(el => {
                    children.push(el)
                })
            }
        }
        newRouter.children = children
    }
   
    return newRouter
}

var backendManageRouter1 = {
    name: 'BackendManage',
    meta: {
        title: '后台管理',
        icon: 'index-management'
    },
    children: [{
        path: 'user-manage',
        name: 'UserManage',
        noCompoent: true,
        meta: {
            title: '用户管理',
            icon: 'rule-definition'
        },
        alwaysShow: true,
        children: [{
            path: 'user',
            name: 'User',
            meta: {
                title: '用户管理',
                icon: 'quality-control'
            },
            noCompoent: true,
            children: [
                {
                    path: 'a',
                    name: 'ad',
                    meta: {
                        title: 'ad管理',
                        icon: 'quality-control'
                    },
                }
            ]
        }, {
            path: 'role',
            name: 'Role',
            meta: {
                title: '角色管理',
                icon: 'rule-task-monitor'
            }
        }]
    }]
}

delteFakeParent这个函数做的就是创建一个router副本,遍历它的children,当这个路由被标记为noCompoent: true,就把它替换成它的children,回溯的过程中如果router是一个数组就代表这个router是被替换过,那么就遍历它,把它每一项放到router.children里面,这样就可以做到跟它其他children平级。
修改了这个之后要记着把真实router和菜单router同时暴露出去,菜单的项目是读取store中的permission.js的routers,那么这里set-router一方面要处理真是router和菜单router,需要增加一个state

3. 使用vuex存储数据
上面那个方案也只是针对二级路由组件不需要显示出来,那么可以放到一级路由的children里面,但是如果是有需要的话,还是使用vuex来存储数据比较好。

Logo

前往低代码交流专区

更多推荐