需求:现在有三个页面,首页A,带搜索框以及表格的页面B,点击B中的表格详情链接到详情页面的C 

当从A->B->C 再从C->B回退到B时希望能显示B中搜索框和表中的信息即C的上一页面的历史信息。

解决方案:1.采用web存储,发现逻辑麻烦。2.利用vue的keep-alive 我们将B中的数据缓存下来

方案1

1.在App.vue中

<keep-alive>
          <router-view v-if="$route.meta.keepAlive">
              <!-- 这里是会被缓存的视图组件 -->
          </router-view>
      </keep-alive>

      <router-view v-if="!$route.meta.keepAlive">
          <!-- 这里是不被缓存的视图组件 -->
      </router-view>

2.在router/index.js中需要缓存的组件内部加上meta:true即可(B页面)

{
          path: "/ProjectDetail",
          name:'ProjectDetail',
          component: ProjectDetail,
          meta:{
              keepAlive:true,
          }
      },

遇到的问题:C返回到页面B时,B确实是被缓存了,network也没有请求,但是我们在返回到A,从A进入到B中发现数据并没有更新,没有向后台发送请求,因为是直接读取了缓存中的B页面,我现在的需求是A->B 前进刷新 C->B 后退缓存

3.在要缓存的页面B的beforeRouteLeave((to,from,next)=>{next()})路由钩子函数中根据条件设置to.meta.keepAlive即可

beforeRouteLeave(to,from,next){
        if(to.name==='Detail'){
            if(!from.meta.keepAlive){
                from.meta.keepAlive=true;//当我们进入到C时开启B的缓存
            }
            next()
        }else{
            from.meta.keepAlive=false;
            this.$destroy();//销毁B的实例
            next();//当我们前进的不是C时我们让B页面刷新
        }
    },

遇到的问题:第一次A->B->C 再从C->B->A 正常 ,第二次A->B->C C->B发现没有缓存,network中有请求。原因是使用this.$destory()销毁实例后,无论怎么对B设置keepAlive 都无效尴尬。无奈百度发现的解决方法是若不是第一次进入就强制刷新一次缓存页面。

4.在main.js中使用router.beforeEach((to,from)=>{})

router.afterEach((to, from) => {
    // ...
    console.log(from);
    if(from.name==='Home' &&  to.name==='ProjectDetail'){
        let isRefresh=sessionStorage.getItem('isRefresh');
        console.log(isRefresh)
        if(isRefresh==='0'){
            sessionStorage.setItem('isRefresh',null);
            window.location.reload()
        }else{
            sessionStorage.setItem('isRefresh',0);
        }
    }else if(to.name==='Home'&& from.name==='ProjectDetail'){
        sessionStorage.setItem('isRefresh',0)
    }
});

目前暂时解决了问题,但是用户体验感不好 。。哈哈,结果又发现了另一种方法

方案2

1.在app.vue中

<keep-alive :include=includedComponents :exclude=excludedComponents>
  <router-view></router-view>
</keep-alive>

其中include代表着要缓存的,exclude代表着非缓存的  那啥 发现includedComponents和excludedComponents 加引号 缓存和非缓存无效

在computed中

    includedComponents:state=>state.includedComponents,
    excludedComponents:state=>state.excludedComponents

2.在store.js中

show(state,data){
            state.includedComponents=data
        }

3.在B页面 ProjectDetail为B组件的name对应的值

 beforeRouteLeave(to,from,next){
      if(to.name==='Detail'){
          next()
      }else{
          this.$store.commit("show","");B->非C页面
          next()
      }
    },
    activated(){
      this.$store.commit("show","ProjectDetail");//缓存B页面
      console.log('activated')
    },
    deactivated(){
        console.log('deactivated')
    },

keep-alive的生命周期钩子函数

开启缓存后,第一次进入执行created,activated等,退出时执行deactivated

第二次不执行created等直接执行activated

使用include和exclude的注意点:

1.建议在每个组件内部添加name:xx

2.若将include设置空""貌似每个页面都将会缓存

3.exclude的优先级高于include 使用exclude后,activated和deactivated是不会被激活的

<!-- 逗号分隔字符串,只有组件a与b被缓存。这样使用场景变得更有意义了 -->
<keep-alive include="a,b">
  <component :is="view"></component>
</keep-alive>

<!-- 正则表达式 (需要使用 v-bind,符合匹配规则的都会被缓存) -->
<keep-alive :include="/a|b/">
  <component :is="view"></component>
</keep-alive>

<!-- Array (需要使用 v-bind,被包含的都会被缓存) -->
<keep-alive :include="['a', 'b']">
  <component :is="view"></component>
</keep-alive>
Logo

Vue社区为您提供最前沿的新闻资讯和知识内容

更多推荐