最近公司需要完成三级目录缓存,记录下遇到的坑。路由由后端动态提供的,二级目录的路由配置如下

{
    path: '/guide',
    component: Layout,
    redirect: '/guide/index',
    children: [
      {
        path: 'index',
        component: () => import('@/views/guide/index'),
        name: 'Guide',
        meta: { title: 'Guide', icon: 'guide', noCache: true }
      }
    ]
  },

跟后端协商,返回的路由数据格式跟我们在自己配置的静态路由即可。页面缓存,根据vue提供的keep-alive这个标签来进行缓存,include里表示可以缓存的组件name名称,exclude表示不缓存某些组件。

<template>
  <section class="app-main">
    <transition name="fade-transform" mode="out-in">
      <keep-alive :include="cachedViews" exclude="monitorList">
        <router-view :key="key" />
        <!-- <router-view /> -->
      </keep-alive>
    </transition>
  </section>
</template>

 三级目录缓存

1.第一种写法(bug)

先写一个公共组件(名字随便取),用了显示三级目录,由于路由是后端返回的,当然还需要后端帮个忙,遇到有三级或者多级的name的名称都要用你这个组件的相同的name

下面是ParentView组件;

<template>
  <router-view />
</template>
<script>
export default {
  name: "ParentView"
};
</script>

后台接口返回的路由:

当然传到前端还需要做一个判断来处理,对component的name是ParentView进行处理。

在cacheviews:【‘ParentView’】默认加了2级的目录的组件名

// 遍历后台传来的路由字符串,转换为组件对象
function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) {
  return asyncRouterMap.filter(route => {
    if (type && route.children) {
      route.children = filterChildren(route.children)
    }
    if (route.component) {
      // Layout ParentView 组件特殊处理
      if (route.component === 'Layout') {
        route.component = Layout
      } else if (route.component === 'ParentView') {
        route.component = ParentView
      }  else {
        route.component = loadView(route.component)
      }
    }
    if (route.children != null && route.children && route.children.length) {
      route.children = filterAsyncRouter(route.children, route, type)
    }
    return true
  })
}

但是你发现页面其实没缓存,这个你想会不会是,ParentView组件也没加keep-alive,然后你开心的去加了一波,发现可以缓存了。=。=

但是这样会有问题,当你删除这个页面,下次再打开这个页面,还是缓存上次页面的内容。是因为你关闭并没有删除,parentview导致的。后来想,看能不能把第二层router-view给删除,这样子,保存的都是2级目录名称,这样就可以实现缓存,也规避了刚才的问题。

方法二: 

在路由守卫,加个方法,去掉parentview这个目录,这样子就可以实现多级目录缓存。

//对多级目录进行处理
 function handleKeepAlive (to) {
  if (to.matched && to.matched.length > 2) {
    for (let i = 0; i < to.matched.length; i++) {
      const element = to.matched[i]
      if (element.components.default.name === 'ParentView') {
        to.matched.splice(i, 1)
        handleKeepAlive(to)
      }
    }
  }
}

 

这样子,外层就不会在套一层ParentView了。 

不缓存的原因:(1) name的名称一定要一样

                         (2)noCache的值要是false

                         (3)查看cacheViews是否包含需存的组件名

希望对大家有所帮助,总结的不太好,勿喷,哈哈哈。

Logo

前往低代码交流专区

更多推荐