一般的后台管理系统功能很多,都需要多级菜单,但是在这种项目中,性能keep-alive往往很不稳定,有时某个页面可以缓存,但点击几下,缓存就丢失了;有时由于某种原因它没有被缓存。出现这个问题的原因是:多级路由组件嵌套。具体分析:如果一个后台管理系统有一个main.vue是所有页面的框架,有这么一段代码然后创建父菜单,页面为ChildView.vue,里面的代码下面的假设这个父菜单中有两个子菜单,分别是A和B,然后A设置缓存(keepAlive=true),B不缓存(keepAlive=假);当点击A菜单时,系统会缓存ChildView.vue组件。当B菜单被点击时,ChildView.vue组件被销毁,因为B设置没有被缓存。这就是keep-alive失败的根本原因。还有更复杂的。例如,可以缓存同一个菜单中的子菜单,但点击另一个父菜单或父菜单下的子菜单则不缓存。原理和上面分析的一样,就是多级菜单,多个共享组件导致的keepAlive缓存失效,keepAlive根本没有考虑页面缓存的复杂性。下面的表现也是这个问题的原因之一:activated和deactivated从A页面进入B页面发现不触发会重复触发A页面的接口调用分析问题:由于有多个router-视图嵌套而且是共享导致的,所以如果只有一个router-view,即只需要main.vue作为frame中所有页面的容器,就不会出现这个问题。其实,多级菜单是否对项目或业务完全没有影响,只是界面展示所需要的,让用户可以更快捷地点击到自己需要的功能页面。在这种情况下,显示的菜单仍然是多级的,将实际的路由器做成一级,将显示的菜单与业务路由器分开。解决问题:首先,将配置好的多级路由器用vuex缓存起来,作为显示菜单使用。然后将router转为一级菜单,通过addRoutes异步添加到router中。部分示例代码:constformatRouter=(routes,newRoutes=[])=>{routes.map(item=>{if(item.children&&item.children.length>0)formatRouter(item.children,newRoutes);newRoutes.push(item);})returnnewRoutes;}letflatRoutes=formatRouter(routes);router.addRoutes(flatRoutes);然后面包屑导航需要调整,大部分逻辑是从route.matched中获取的,但是现在router都是一级的,我们需要从显示的菜单数据中获取面包屑导航数据。示例代码:/***自定义搜索字段,根据最后一层的某个字段搜索完整树(整个父类)*@param{*}val待比较的值*@param{*}data要查找的数据*@param{*}fKey要查找比较的字段*/constrecursiveTreeByLastLevel=(val,data,fKey='value')=>{letrData=[];for(leti=0,len=data.length;i0){rData=rData.concat(recursiveTreeByLastLevel(val,data[i].children,fKey));如果(rData.some(item=>item[fKey]===val))返回rData;}if(data[i][fKey]===val)返回rData;数据=[];}returnrData;}router.afterEach((to,from,next)=>{varrouterList=recursiveTreeByLastLevel(to.name,store.state.sidebarMenu,'name')store.commit('setCrumbList',routerList)//通过vuex缓存})完成,收工!