keep-alive数据缓存

997 阅读2分钟

Vue实现返回上一页不请求数据

我们通常会将通过接口请求数据的方法放在==created== 或者 ==mounted==这两个生命周期中的一个里面调用。

但是我们知道,不管是我们刚进入这个页面还是从其他页面返回这个页面,这些生命周期都会走一遍。

问题:

所以,即使你跳转到下级页面选好你所需的数据返回上一页时,你所回填的数据又被从接口请求回来的数据给覆盖了。。。,这并不是我们想要的效果!!!

vue提供了一个keep-alive组件用来缓存组件,避免多次加载相应的组件,减少性能消耗

缓存所有页面

如果你想缓存所有的页面,只需要修改下app.vue中的代码即可

// app.vue
    <template>
      <div id="app">
        <keep-alive >
          <router-view></router-view>
        </keep-alive>
        <tabBar/>
      </div>
    </template>

缓存部分页面

使用router.meta属性
// app.vue
<template>
      <div id="app">
        <keep-alive >
          <router-view v-if="$route.meta.keepAlive"></router-view>
        </keep-alive>
        <router-view v-if="!$route.meta.keepAlive"></router-view>
        <tabBar/>
      </div>
    </template>
// router.js
{
      path: '/keep-alive',
      name: 'TestKeepAlive',
      component: TestKeepAlive,
      meta: {
        keepAlive: true, //此组件需要被缓存
        isBack: false, // 用于判断上一个页面是哪个        
      }
},
// TestKeepAlive.vue
<template>
    <div>
        <button @click="toDetail">去详情页</button>
        {{ msg }}---------{{ str }}
    </div>
</template>
<script>
    export default {
        data() {
            return {
                msg:'我是首页',
                str:'', // 加载页面后执行获取数据的方法,插入到此(从后台获取数据)
                isFirstEnter:false // 是否第一次进入,默认false
            }
        },
        methods: {
            getData() {
                // getData方法,模拟从后台请求数据
                this.str = "我是通过调用方法加载的数据。。。";
                console.log('getData');                
            },
            toDetail() {
                this.$router.push('/keep-detail')
            }
        },
        created() {
            this.isFirstEnter=true;
            console.log('created');
            // 只有第一次进入或者刷新页面后才会执行此钩子函数
            // 使用keep-alive后(2+次)进入不会再执行此钩子函数
        },
        beforeRouteEnter(to, from, next) {
            
            if(from.name=='TestKeepAlive1'){
                to.meta.isBack=true;
                //判断是从哪个路由过来的,
                //如果是TestKeepAlive1过来的,表明当前页面不需要刷新获取新数据,直接用之前缓存的数据即可
            }
            next();
        },
        activated() {           
            if(!this.$route.meta.isBack || this.isFirstEnter){
                // 如果isBack是false,表明需要获取新数据,否则就不再请求,直接使用缓存的数据
                // 如果isFirstEnter是true,表明是第一次进入此页面或用户刷新了页面,需获取新数据
                this.str=''// 把数据清空,可以稍微避免让用户看到之前缓存的数据
                this.getData();
            }
            console.log('actived');
            // 恢复成默认的false,避免isBack一直是true,导致下次无法获取数据
            this.$route.meta.isBack=false
            // 恢复成默认的false,避免isBack一直是true,导致每次都获取新数据
            this.isFirstEnter=false;
        },
    }
</script>

isFirstEnter

用于记录当前页面是否是第一次进入的

在 created 生命周期改变 isFirstEnter 的值
  -- 只有第一次进入改页面 或者 B页面 刷新之后返回该页面 才会执行此钩子函数

页面第一次加载生命周期

beforeRouteEnter ==> created ==> mounted => activated

当从 A 页面 =》B页面 =》A页面

B页面如果美国数据更新的话
A页面的生命周期:
beforeRouteEnter ==> activated