• vue keepAlive+include动态缓存


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

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

  • 相关阅读:
    Future接口和Callable接口以及FeatureTask详解
    puppet的使用:ERB模板介绍
    puppet的使用:依赖关系整理
    数字证书常见格式整理
    c3p0配置文件
    dockerfile简述
    Grape简介
    keytool和openssl生成的证书转换
    Grape教程-params
    耿丹CS16-2班助教总结
  • 原文地址:https://www.cnblogs.com/dongzhi1111/p/16306630.html
Copyright © 2020-2023  润新知