vue keep-alive多级嵌套路由缓存
花名森林 人气:16现状(问题):
keep-alive 组件对第三级及以上级的路由页面缓存失效
探索方案:
方案1、直接将路由扁平化配置,都放在一级或二级路由中
方案2、再一层缓存组件用来过渡,并将其name配置到include中
实现方式
方案1不需要例子,按规则配置路由就行重点介绍方案2
因为我用了vue-element-admin做了架构,并且项目中我将菜单和路由全部通过服务端返回做了统一配置,所以我只能用方案2来实现。
直接看原有代码(问题代码)
// src/layout/component/AppMain.vue <template> <section class="app-main"> <transition name="fade-transform" mode="out-in"> <keep-alive :include="cachedViews"> <router-view :key="key" /> </keep-alive> </transition> </section> </template> <script> export default { name: 'AppMain', computed: { cachedViews() { return this.$store.state.tagsView.cachedViews }, key() { return this.$route.path } } } </script>
我从后端那到数据后,根据树形结构做了处理(在store里写的,只展示出关键代码)
// 拿到数据先循环第一层将Layout付给组件 generateRoutes({ commit }, routeList) { return new Promise(resolve => { routeList.forEach(items => { items.component = Layout // 如果有子菜单直接再循环赋值 items.children = changeAsyncRoutes(items.children) }) commit('SET_ROUTES', routeList) resolve(routeList) }) } function changeAsyncRoutes(routes) { const res = [] routes.forEach(route => { const tmp = { ...route } if (tmp.children && tmp.children.length !== 0) { // 若有子级 先创建router-view容器,再去递归(重点重点重点) tmp.component = { render: c => c('router-view') } tmp.children = changeAsyncRoutes(tmp.children) } else { // 没有子级菜单直接将component字符串解析成组件对象 tmp.component = importMethod(tmp.component) } res.push(tmp) }) return res }
这种写法已经很完美了,可惜,我遇到了三级菜单不能缓存的问题
直接上解决问题的代码
1、新建MenuMain.vue组件如下
// src/layout/component/MenuMain.vue // 提供多级菜单的容器 <template> <keep-alive :include="cachedViews"> <router-view :key="key" /> </keep-alive> </template> <script> export default { name: 'MenuMain', // 必须命名 computed: { cachedViews() { return this.$store.state.tagsView.cachedViews }, key() { return this.$route.path } } } </script>
2、将此容器取代处理数据时render的 router-view 容器
// 引入组件 import MenuMain from '@/layout/components/MenuMain' function changeAsyncRoutes(routes) { const res = [] routes.forEach(route => { const tmp = { ...route } if (tmp.children && tmp.children.length !== 0) { // 注意看着里 tmp.component = MenuMain // { // render: c => c('router-view') // } tmp.children = changeAsyncRoutes(tmp.children) } else { tmp.component = importMethod(tmp.component) } res.push(tmp) }) return res }
3、把store中的 cachedViews 数组中始终保存MenuMain组件的名称
cachedViews: ['MenuMain']
加载全部内容