ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

vue keepAlive+include动态缓存

2022-05-24 18:32:25  阅读:257  来源: 互联网

标签:缓存 layout name vue 页面 A2 B2 include keepAlive


首先,做这个目的是产品多次提出页面缓存的问题,导致客户抱怨,一直没有解决,那能怎么办,只能我上了

网上找了很多方案,发现通过条件控制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:'layoutIndex'

 

 include缓存是通过页面name去缓存的,所以声明后就相当于缓存

 

 

PS

  1.不管跳转的页面要不要缓存,都需要填写name,加入待缓存列表

  2.B2页面要跳到B2_A2(即A2页面),那么B2_A2必须加入到B1_child的子列表,否则不生效

   所以路由跳转以name的形式跳转 this.$router.push({name:'B2_A2'})

  3.一种情况就是共用A2页面,页面name有多个,都需要进行缓存,可以通过组件形式引入,再分别设置name

 

标签:缓存,layout,name,vue,页面,A2,B2,include,keepAlive
来源: https://www.cnblogs.com/dongzhi1111/p/16306630.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有