首先,做这个目的是产品多次提出页面缓存的问题,导致客户抱怨,一直没有解决,那能怎么办,只能我上了
网上找了很多方案,发现通过条件控制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
浙公网安备 33010602011771号