首先,做这个目的是产品多次提出页面缓存的问题,导致客户抱怨,一直没有解决,那能怎么办,只能我上了
网上找了很多方案,发现通过条件控制include的值是最好的方案,而不是之前的判断meta里面的值
使用include的方案也差不多是通过传参去判断,但是不怎么优雅,相对于新项目可以这样,但是老项目就是大改造
本项目是基于左侧菜单选择,然后右侧展示内容去设计
实现方案
1.路由配置,获取路由列表
2.监听路由变化,获取当前页面的路由名称进行保存或销毁
3.页面name属性声明,声明即缓存
1.路由配置
1.首先配置路由列表
import Router from "vue-router"; import Vue from "vue"; import layout from '@/views/layout/layout' Vue.use(Router); const routersList = [ { path: '/', component: (resolve) => require(["@/views/layout/index"], resolve), children: [{ path: 'A', component: layout, children: [ { path: '', name: 'A1', //标注了name的页面为待缓存列表 component: () => import('@/views/layout/test1.vue'), }, { path: 'A1_child', //A1_child的子列表为内部跳转页面,也可抽出跟A1同级(路径名称随意) component: layout, children: [ { path: 'A2', name: 'A2', component: () => import('@/views/layout/test2.vue'), }, { path: 'A2_child', component: layout, children: [{ path: 'A3', name: 'A3', component: () => import('@/views/layout/test3.vue'), },] }, ] }, ] },{ path: 'B', component: layout, children: [ { path: '', name: 'B1', component: () => import('@/views/layout/test4.vue'), }, { path: 'B1_child', component: layout, children: [ { path: 'B2', name: 'B2', component: () => import('@/views/layout/test5.vue'), }, { path: 'B2_A2', name: 'B2_A2', component: () => import('@/views/layout/test2.vue'), }, ] }, ] }] } ];
export {routersList}
以上是配置的两套路由
1.A1->A2->A3 A1跳转A2跳转A3
A3->A2->A1 A3返回,A2缓存;A2返回,A1缓存
2.B1->B2->B2_A2 B1跳转B2跳转B2_A2
B2_A2->B2->B1 B2_A2返回,B2缓存;B2返回,B1缓存
这样很清楚知道缓存的东西(原谅我不会画图)
定义
name:标注了name的页面为待缓存列表,只有这些页面才会被缓存
A1_child:列表为内部跳转页面,相当于子列表,也可抽出跟A1同级
2.layout组件,用于每层页面缓存
<template> <keep-alive :include="include"> <router-view></router-view> </keep-alive> </template> <script> export default { computed:{ include(){ return this.$store.state.include }, }, } </script>
2.监听路由变化,获取当前页面的路由名称进行保存或销毁
App.vue页面
<template> <div id="app"> <keep-alive :include="include"> <router-view></router-view> </keep-alive> </div> </template> <script> import CacheClass from '@/assets/js/config/CacheClass' export default { computed:{ include(){ return this.$store.state.include }, }, watch: { $route(to,from) { console.log('路由变化',this.$route) this.cache.queryModule(to,from) }, }, mounted() {this.cache=new CacheClass({instance:this}) } } </script>
CacheClass.js
import {routersList} from '@/router' class CacheClass { constructor(params={}) { this.routersList=routersList //路由列表 this.instance=params.instance //vue实例 this.cacheList=[] //模块缓存列表 this.includeList=[] this.init() } init(){ this.getCacheList() } getCacheList(){ const fn=(list,obj)=>{ for(let i in list){ if(list[i].children&&list[i].children.length){ fn(list[i].children,obj) }else{ if(list[i].name){ if(!obj.module) obj.module=list[i].name obj.children.push(list[i].name) } } } } const tmp=[] for(let i in this.routersList){ tmp.push({ module:'', children:[] }) fn(this.routersList[i].children,tmp[tmp.length-1]) } this.cacheList=tmp } queryModule(to,from){ if(!to.name) return // console.log(to,from) // console.log(this.cacheModule,'当前模块') let cacheList=this.cacheList //查出当前路由所在的列表 let cacheName='' let list=[],otherList=[] //其他列表 cacheList.map(item=>{ if(item.module!==this.cacheModule) { otherList.push(item) }else{ list=list.concat(item.children) } }) // console.log('不存在列表',otherList) // console.log('列表',list) const reset=()=>{ otherList.map(item=>{ if(item.children.includes(to.name)){ cacheName=item.module } }) this.cacheModule=cacheName if(cacheName){ console.log('设置模块') this.includeList=[to.name] this.setInclude() }else{ console.log('清空模块') this.includeList=[] this.setInclude() } } this.includeList=JSON.parse(JSON.stringify(this.instance.$store.state.include)) //获取缓存列表 if(list.length) { if(list.includes(to.name)){ console.log('包含模块') if(!this.includeList.includes(to.name)){ //第一次会记录模块(页面都加进去,只要组件不加name就不生效) console.log('添加',to.name) this.includeList.push(to.name) this.setInclude() }else if(this.includeList.includes(from.name)){ //模块返回检查清空 console.log('移除',from.name) const index=this.includeList.findIndex(item=>item===from.name) if(index>-1) { this.includeList.splice(index,1) this.setInclude() } } }else{ console.log('不包含模块,其他模块查找1') reset() } }else{ console.log('不包含模块,其他模块查找2') reset() } console.log('当前路由值',this.includeList) } setInclude(){ this.instance.$store.commit('setInclude',this.includeList) } } export default CacheClass
setInclude(state, e){ state.include=e }
3.页面name属性声明,声明即缓存
name:'A1'
include缓存是通过页面name去缓存的,所以声明后就相当于缓存,值与路由定义的name保持一致
PS
1.不管跳转的页面要不要缓存,都需要填写name,加入待缓存列表
2.B2页面要跳到B2_A2(即A2页面),那么B2_A2必须加入到B1_child的子列表,否则不生效
所以路由跳转以name的形式跳转 this.$router.push({name:'B2_A2'})
3.一种情况就是共用A2页面,都需要进行缓存,页面name怎么设值,可以通过组件形式引入,再分别设置name