Vue 应用 <keep-alive include> 实现多级 <router-view> 缓存,有限档次缓存

应用 <keep-alive> 实现缓存目前有三种办法办法

办法一:

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

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

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

    <keep-alive> <router-view v-if="$route.meta.keepAlive"/></keep-alive><router-view v-if="!$route.meta.keepAlive"/>

    这种办法是比拟早版本时应用的办法,过后<keep-alive>还没有include属性。这个办法尽管不便,然而会带来很多bug,比方无奈应用<transition>、缓存了不必要的,用来实现嵌套路由操作的<router-view>布局组件等。

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

    因而这里重点讲办法二(正在应用的):

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

    2.应用<keep-alive>include属性,来实现动静的组件缓存。

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

    首先咱们须要晓得keep-alive能够依据include中的值来匹配以后路由对应组件的name属性(!!不是路由的name哦,是组件的name),来判断这个路由中的组件是否须要缓存。因而咱们只须要将keepAliveList: []里保留的须要缓存的路由组件name数组传入include即可

    因而应用起来就像这样

    <keep-alive :include="keepAliveList"> <router-view :key="key"/></keep-alive><script>export default { name: 'index', data () { return { keepAliveList: this.$store.getters.getKeepAliveList, } }, computed: { // 获取缓存列表 getKeepAliveList () { return this.$store.getters.getKeepAliveList }, key () { return this.$route.path } }, watch: { getKeepAliveList (n, o) { this.keepAliveList = n } }}</script>

    然而:

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

    比方我有上面的三层构造:

{     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`    <template> <router-view/></template><script>export default { name: 'layout'}</script>

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

咱们能够发现,keep-alive只缓存到第一层,也就是<layout/>这个组件,而这个组件只是一个<router-view/>组件,这显著不是咱们想要的。

咱们须要把<layout/>这个无用的组件从<keep-alive> <router-view/> <keep-alive/>之中提出, 换句话说是将<menu-3/>晋升到<keep-alive>能缓存的那一层,像这样

如何解决?

须要把嵌套的<router-view>拍平

也就是在路由守卫中增加一个将无用的 layout 布局过打消的办法:

// 为什么应用afterEach而不会beforeEach看handleKeepAlive中的正文router.afterEach((to, from) => { handleKeepAlive(to)}/** * 递归解决多余的 layout : <router-view>, * 让须要拜访的组件放弃在第一层 index : <router-view> 之下 * @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 移除时

layout 移除之后

办法三

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