vue1805 / vue-baseKnowdeledge

1 stars 0 forks source link

缓存组件keep-alive的使用 #14

Open yangkaiyangyi opened 6 years ago

yangkaiyangyi commented 6 years ago
缓存组件keep-alive的使用

一.使用场景

    在实际的项目开发中,我们或多或少会遇见一种情况———有些组件我们是没有必要多次进行渲染。例如我们从一个页面A路由跳转到另一个页面B,这时返回页面A时我们需要页面A保持离开前的状态不改变,此时就是keep-alive大展神功的时候了,下面我们一起来看一看keep-alive是如何使用的。

二.keep-alive用法

    1.缓存路由

        想要完成缓存路由的操作,我们需要以下几步操作

        ①.配置路由信息

        ②.创建keep-alive标签

        ③.通过v-if来判断需要缓存那些路由

<keep-alive>
    <router-view v-if = "$route.meta.keepAlive"></router-view>
</keep-alive>
//  除了需要缓存的路由 还要创建一个非缓存路由的入口
<router-view v-if = "!$route.meta.keepAlive"></router-view>

//路由配置
routes: [
   {
    path: '/Message',
    name: 'Message',
    component: Message,
    meta: {
      title: 'xxxxx',
      keepAlive:true   //需要被缓存
      }
    },
    {
    path: '/Midware',
    name: 'Midware',
    component: MidwarePage,
    meta: {
      keepAlive:false   //不需要被缓存
      },
    }
]
    2.缓存组件

    keep-alive提供了两个Props:

  include - 字符串或正则表达式。只有匹配的组件会被缓存。
  exclude - 字符串或正则表达式。任何匹配的组件都不会被缓存。
     这两个属性可以让我们选择性的来缓存某个组件或者路由,这样为我们的操作提供了灵活性,操作如下:

     ①.组件注册name

     ②.创建keep-alive标签

     ②.通过include进行缓存

//app.vue
<keep-alive :include="componentName">
    <router-view ></router-view>
</keep-alive>
export default {
  data(){
      componentName: ['storeTestA']
  }
}
//storeTestA.vue
export default {
  name:'storeTestA',
  data(){
  }
}
     exclude这里就不赘述了 用法是一样的,但是有一点需要明确,exclude的优先级是大于include的:

//这里使用的是逗号分隔字符串,上面例子中使用的是数组形式,还有正则表达式的形式,需要的时候了解下
<keep-alive include="a,b" exclude="a">
    //只有a不被缓存
    <router-view></router-view>
</keep-alive>
   3.keep-alive提供的两个周期函数

  activated:keep-alive 组件激活时调用
  deactivated:keep-alive 组件销毁时调用

三.keep-alive带来的问题

     keep-alive进行缓存后,这个组件或者路由的所有都会被缓存住。例如从这个页面A到页面B,此时页面B回到页面A,页面A被缓存是正确的,而后会发现页面C到页面A,发现页面A,页面A还是被缓存住的,此时与我们的业务就有了冲突,这时候哦我们怎么办呢????

首先我们先了解一些路由钩子:

    全局守卫:

router.beforeEach 全局前置守卫 进入路由之前

router.beforeResolve 全局解析守卫(2.5.0+) 在beforeRouteEnter调用之后调用

router.afterEach 全局后置钩子 进入路由之后

     使用方法: 

   // main.js 入口文件    
   import router from './router'; // 引入路由
   router.beforeEach((to, from, next) => { 
      next();
   });
   router.beforeResolve((to, from, next) => {      
      next();
   });
   router.afterEach((to, from) => {
      console.log('afterEach 全局后置钩子');
   });
to,from,next 这三个参数:
to和from是将要进入和将要离开的路由对象,路由对象指的是平时通过this.$route获取到的路由对象。

next:Function 这个参数是个函数,且必须调用,否则不能进入路由(页面空白)。

next() 进入该路由。

next(false): 取消进入路由,url地址重置为from路由地址(也就是将要离开的路由地址)。

next 跳转新路由,当前的导航被中断,重新开始一个新的导航。

我们可以这样跳转:next('path地址')或者next({path:''})或者next({name:''})
且允许设置诸如 replace: true、name: 'home' 之类的选项
以及你用在router-link或router.push的对象选项。

     路由组件内的守卫:
beforeRouteEnter 进入路由前

beforeRouteUpdate (2.2) 路由复用同一个组件时

beforeRouteLeave 离开当前路由时

     使用方法:

  beforeRouteEnter (to, from, next) {    
    // 在路由独享守卫后调用 不!能!获取组件实例 `this`,组件实例还没被创建
  },
  beforeRouteUpdate (to, from, next) {    
    // 在当前路由改变,但是该组件被复用时调用 可以访问组件实例 `this`    
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,   
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
  },
  beforeRouteLeave (to, from, next) {    
     // 导航离开该组件的对应路由时调用,可以访问组件实例 `this`
  }
    下面重点说一下我们即将使用的beforeRouteEnter访问this问题:

         因为钩子在组件还没有创建实力的时候调用,所以无法使用组件实例this。但是可以传一个回调给next来访问组件实例。

    至此,我们的问题就完美解决了:

beforeRouteEnter (to, from, next) {
    next(vm => {
        //清除缓存  通过路径来判断
        if (from.path.includes('/请求地址')){
          //这个路径来的 则不操作
        } else {
         //这里可以进行一系列的清除操作
            vm.tableData = [];
            vm.form = {};
            vm.queryParams = {};       
        }
    });
},

注:触发钩子完整顺序:

将路由导航、keep-alive、和组件生命周期钩子结合起来的,触发顺序,假设是从a组件离开,第一次进入b组件:

        1. beforeRouteLeave:路由组件的组件离开路由前钩子,可取消路由离开。

        2.beforeEach: 路由全局前置守卫,可用于登录验证、全局路由loading等。

        3.beforeEnter: 路由独享守卫

        4.beforeRouteEnter: 路由组件的组件进入路由前钩子。

        5.beforeResolve:路由全局解析守卫

        6.afterEach:路由全局后置钩子

        7.beforeCreate:组件生命周期,不能访问this。

        8.created:组件生命周期,可以访问this,不能访问dom。

        9.beforeMount:组件生命周期

        10.deactivated: 离开缓存组件a,或者触发a的beforeDestroy和destroyed组件销毁钩子。

        11.mounted:访问/操作dom。

        12.activated:进入缓存组件,进入a的嵌套子组件(如果有的话)。

        执行beforeRouteEnter回调函数next。