Vue-Router中使用keep-alive及在transition中的动画过度问题

当我们使用Vue来回切换页面,并希望保持页面组件状态的时候,会用到Vue的keep-alive抽象组件。以下为官网中的说明:

包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。和 相似,是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在父组件链中。

这里注意,必须包裹动态组件时,缓存机制才会生效

下面为简单的使用方式:

<keep-alive>
  <router-view :key="key"></router-view>
</keep-alive>

这里的key属性,我使用的是当前组件的完整路径。

computed:{
    key(){
      return this.$route.fullPath;
    }
  }

之后,每次切换路由,之前组件的状态在返回时会被保存起来。
当然,如果功能上只需保存指定组件状态,而不是所有组件状态,可以在keep-alive标签内加上includeexclude属性。
他们分别接受三种类型的值:

  • 字符串格式
      <keep-alive include="account">
        <router-view :key="key"></router-view>
      </keep-alive>

上面的account必须与子组件的name选项保持一致

  • 数组格式
      <keep-alive :include="['account','comment']">
        <router-view :key="key"></router-view>
      </keep-alive>
  • 正则表达式
      <keep-alive :include="/account|comment/">
        <router-view :key="key"></router-view>
      </keep-alive>

使用数组或正则筛选组件时,属性include必须使用v-bind修饰符。

此外,exclude的优先级大于include,看下面的例子:

      <keep-alive :include="/account|comment/" :exclude="/account/">
        <router-view :key="key"></router-view>
      </keep-alive>

例子中,使用正则表达式,分别缓存accountcomment组件状态,并设定不缓存account组件状态,执行后的效果为,页面切换回comment时,状态保持,而account被设定为了初始状态,没有保存之前的输入内容。

在实践中遇到的问题
当页面包含多个使用同一个组件渲染的区域时,由于组件的name属性相同,keep-alive不能缓存指定的区域,可以通过设定Vue-Router来解决这个问题。看以下代码:

export default new Router({
  mode: "history",
  routes: [//路由匹配规则
    { path: "/", redirect: '/account/login' },//重定向到redirect指定的位置
    {
      path: "/account", component: accountInfo,
      redirect: "/account/login", children: [
        { path: "login", component: login },
        { path: "register", component: register },
      ]
    },//path:路由指定url地址,component指定匹配好的组件
    { path: "/comment2", component: comment, meta: { keepAlive: true } },
    { path: "/comment3", component: comment},
    { path: "/comment4", component: comment, meta: { keepAlive: false } }
  ],
  linkActiveClass: 'activeNav'
})

以上Vue-Router设定中,给路径/comment2添加meta: { keepAlive : true}选项来指定只缓存此路由所显示组件的状态。接着在App.vue的template中添加以下代码:

    <div style="position:relative">
      <transition mode="out-in">
        <keep-alive>
          <router-view :key="key" v-if="$route.meta.keepAlive" style="position:absolute;width:100%"></router-view>
        </keep-alive>
      </transition>
      <transition mode="out-in">
        <router-view :key="key" v-if="!$route.meta.keepAlive" style="position:absolute;width:100%"></router-view>
      </transition>
    </div>

这样,页面中切换组件时,需要缓存的组件状态就会被保留了。
上述使用传统的v-if方式,加入两个router-view,此时就如果组件间存在过度动画,就会遇到过渡动画显示异常的问题,即如果组件在同一组transition中切换时,过度动画显示正常,而当切换不同transition时,过度动画会重叠。我的解决方案是修改:
原先在没有使用两个transition时,过度动画全局样式我是这么写的:

.v-enter-active,
.v-leave-active {
  transition: all 0.6s ease;
}

参考官网的过度动画生命周期后,现在改为:

.v-enter-active{
  transition: all 0.6s ease;
  transition-delay: 0.6s;
}
.v-leave-active{
  transition: all 0.6s ease;
}

这样,我们让动画在进入前等待0.6秒后,开始进入状态,与动画离开的持续时间吻合后,就能做到与不加keep-alive同样顺畅的动画效果了!

你可能感兴趣的:(学习笔记)