Vue中实现页面数据状态保存的几种方式

4,730 阅读2分钟

keep-alive + router meta

在router 的meta添加 keepAlive 属性 使用keep-alive包过router-view组件,并使用meta中的keepAlive判断

// router 路由配置 keepAlive属性
{    
    path: "/",
    component: Layout,
    redirect: "/home",    
    children: [      
        {        
            path: "home",        
            name: "Home",        
            meta: {        
                keepAlive: true       
            },        
            component: () => import("@/views/Home.vue")      
         },      
        {        
            path: "about",        
            name: "About",        
            component: () => import("@/views/About.vue")      
        }    
   ]  
}
// keep-alive组件包裹router-view组件<keep-alive>     
<router-view v-if="$route.meta.keepAlive" :key="key"></router-view> </keep-alive> 
<router-view v-if="!$route.meta.keepAlive" :key="key"></router-view>

keep-alive + component name

使用keep-alive的prop属性 include 设置需要缓存的组件,exclude排除不需要缓存的组件名字,max属性课配置最多缓存数量,超过该数量时会把已缓存组件中最久没有被访问的实例会被销毁掉。 此种方式一定要注意设置正确组件的name

以上两种可以实现指定页面,但是有个问题,不管从缓存的页面跳转到其他任何页面,都缓存了该页面。不能控制缓存页面跳转到指定页面才进行缓存。比如需要缓存的页面A,从A页面可以跳转到B、C页面。现在想实现只有跳转到B页面时才缓存A页面,跳转到C页面不进行缓存。要实现这种动态缓存需要可以使用下面的方法,直接操纵keepalive组件实例的cache属性。

动态移除keepalive组件缓存: 参考 zhuanlan.zhihu.com/p/40374425 keep-alive 默认不支持动态销毁已缓存的组件,所以此处给出的解决方案是通过直接操控 keep-alvie 组件里的 cahce 列表

    beforeRouteLeave:function(to, from, next){
        if (from && from.meta.rank && to.meta.rank && from.meta.rank>to.meta.rank)
        {//此处判断是如果返回上一层,你可以根据自己的业务更改此处的判断逻辑,酌情决定是否摧毁本层缓存。
            if (this.$vnode && this.$vnode.data.keepAlive)
            {
                if (this.$vnode.parent && this.$vnode.parent.componentInstance && this.$vnode.parent.componentInstance.cache)
                {
                    if (this.$vnode.componentOptions)
                    {
                        var key = this.$vnode.key == null
                                    ? this.$vnode.componentOptions.Ctor.cid + (this.$vnode.componentOptions.tag ? `::${this.$vnode.componentOptions.tag}` : '')
                                    : this.$vnode.key;
                        var cache = this.$vnode.parent.componentInstance.cache;
                        var keys  = this.$vnode.parent.componentInstance.keys;
                        if (cache[key])
                        {
                            if (keys.length) {
                                var index = keys.indexOf(key);
                                if (index > -1) {
                                    keys.splice(index, 1);
                                }
                            }
                            delete cache[key];
                        }
                    }
                }
            }
            this.$destroy();
        }
        next();
    },

vuex 或 localStorage 储存状态数据

在beforeRouterLeave里在路由跳转前保存页面状态数据 在路由跳转回来时在mounted里面设置页面状态数据 注意使用beforeRouterLeave时,只能在配置路由的组件里面生效,在配置路由组件的子组件内拦截不成功,需要在父组件中使用$refs 访问子组件的data和method 路由参数存储数据

  1. 使用watch监听页面状态数据变化,
  2. $route.qeury设置路由参数,query对象一定要拷贝,然后调用用$router.push方法,浏览器地址栏参数才会变化
  3. 在页面返回时,在mountedcreated中读取保存路由参数并进行赋值
   detailLessonRadioBtn: {      
            handler(val) {        
                let query = Object.create(this.$route.query);
                query.tab = this.formModel.tabModel;        
                query.subtab = this.detailLessonRadioBtn;        
                this.$router.push({ path: this.$route.path, query });      
           }    
        }
   },
   created() {    
       if (this.$route.query.tab) {      
           this.formModel.tabModel = this.$route.query.tab;      
           if (this.$route.query.subtab) {        
               this.detailLessonRadioBtn = this.$route.query.subtab;      
           }    
        }
   }

localStorage vs sessionStorage

localStorage:

  1. 存储的数据在浏览器的不同tab页和窗口页是共享的,只要有相同的origin
  2. 没有过期时间,即使浏览器关闭电脑关机,数据依然不会被清除 sessionStorage:
  3. 保存的数据只对当前tab页有效,其他tab页访问不到,即使origin相同。不同的tab页拥有不同的sessionStorage
  4. 页面被关闭时,数据会被清除。页面刷新时数据不会清除
  5. 数据可在同一tab页下的不同iframe共享 总结:sessionStorage和localStorage的属性和方法是同样的,sessionStorage在功能上相比localStorage受到了更多的限制