keep-alive处理嵌套深层级的路由方案

Vue 使用 <keep-alive include> 实现多级 <router-view> 缓存,无限层次缓存

使用 实现缓存目前有三种方法方法

方法一:

  1. 在路由元信息中添加缓存标识:

    {
     path: 'json',
     name: 'json',
     meta: {
     ...
     keepAlive: true
     ...
     },
     component: () => import('../views/components/json')
    },

    2 . 使用v-if判断是否缓存

    
     
    
    

    这种方法是比较早版本时使用的方法,当时还没有include属性。这个方法虽然方便,但是会带来很多bug,比如无法使用、缓存了不必要的,用来实现嵌套路由操作的布局组件等。

    然鹅,我有强迫症,不能接受没有动效 ( ̄(00) ̄)

    因此这里重点讲方法二(正在使用的):

    1.将路由元信息中包含keepAlive: true的路由记录下来,并将该路由的name属性为维护在使用vuex中的一个keepAliveList: []里。

    2.使用include属性,来实现动态的组件缓存。

    先说一下include属性,它的值可以是:字符串,正则表达式,数组

    首先我们需要知道keep-alive可以根据include中的值来匹配当前路由对应组件的name属性(!!不是路由的name哦,是组件的name),来判断这个路由中的组件是否需要缓存。因此我们只需要将keepAliveList: []里保存的需要缓存的路由组件name数组传入include即可

    因此使用起来就像这样

    
     
    

    但是:

    如果遇到嵌套的或者嵌套路由(这是很常见的操作),这个时候后面几层中的组件缓存会出问题

    比如我有下面的三层结构:

{
     path: '/menu-1',
     name: 'menu-1',
     // 布局文件 ,用来实现多层嵌套的 组件访问,对于多层次的路由访问来说,这是必须的
     component: layout, 
     children: [
     {
     path: 'menu-2',
     name: 'menu-2',
     component: layout,
     children: [
     {
     path: 'menu-3',
     name: 'menu-3',
     meta: {
     keepAlive: true
     },
     component: () => import('../views/components/menu-3.vue')
     }
     ]
     }
     ]
    }
    
    文件内容 `layout.vue`
    

我想要访问menu-3,在路由之中可视化可以这么看 ( layout 写错了,淦 ):

keep-alive处理嵌套深层级的路由方案_第1张图片

我们可以发现,keep-alive只缓存到第一层,也就是这个组件,而这个组件只是一个组件,这明显不是我们想要的。

我们需要把这个无用的组件从 之中提出, 换句话说是将提升到能缓存的那一层,像这样
keep-alive处理嵌套深层级的路由方案_第2张图片

如何解决?

需要把嵌套的拍平

也就是在路由守卫中添加一个将无用的 layout 布局过消除的方法:

// 为什么使用afterEach而不会beforeEach看handleKeepAlive中的注释
router.afterEach((to, from) => {
 handleKeepAlive(to)
}
​
/**
 * 递归处理多余的 layout : ,
 * 让需要访问的组件保持在第一层 index :  之下
 * @param to
 */
function handleKeepAlive (to) {
 if (to.matched && to.matched.length > 2) {
 for (let i = 0; i < to.matched.length; i++) {
 const element = to.matched[i]
 // 因为import()异步懒加载,第一次获取不到element.components.default.name , 所以不能再beforeEach做,不然第一次访问的界面不缓存第二次才会缓存
 // afterEach就不一样了,这时候可以获取到element.components.default.name了
 if (element.components.default.name === 'layout') {
 to.matched.splice(i, 1)
 handleKeepAlive(to)
 }
 }
 }
}

没有进行 layout 移除时keep-alive处理嵌套深层级的路由方案_第3张图片

layout 移除之后

keep-alive处理嵌套深层级的路由方案_第4张图片

方法三

就是每一层的router-view都包裹一层keep-alive就好了

你可能感兴趣的:(keep-alive处理嵌套深层级的路由方案)