vue进入/离开 & 列表过渡transition

一.transition过渡

1.需求1(优化):想要一种效果,想要ios那种页面切换效果,总而言之就是过渡效果。

附上官网介绍地址:https://cn.vuejs.org/v2/guide/transitions.html

1.

App.vue代码片段如下:

<template>
  <div id="app">
    <transition :name="transitionName">
      <keep-alive>
         <router-view  v-if="$route.meta.keepAlive"></router-view>
      </keep-alive>
    </transition>
    <transition :name="transitionName">
         <router-view v-if="!$route.meta.keepAlive"></router-view>
    </transition>
  </div>
</template>

以上是HTML上的代码,在keep-alive外层,增加transition,并且绑定name属性transitionName(这个是一个变量,用来控制想要加的样式前缀),看了下面的代码你就懂了:

watch: {//使用watch 监听$router的变化
   $route(to, from) {
      //如果to索引大于from索引,判断为前进状态,反之则为后退状态
      if(to.meta.index > from.meta.index){
          //设置动画名称
          this.transitionName = 'slide-left';
      }else{
          this.transitionName = 'slide-right';
      }
   }
}


 

 

import Vue from 'vue';
import VueRouter from 'vue-router'

import Home from '@V/home'
import List from '@V/list'
import Approve from '@V/approve'
import DetailInfo from '@V/detailInfo'
import Info from '@V/info'

Vue.use(VueRouter)

export const routes = [
  {
    path:'/',
    name:'home',
    component:Home,
    meta: {
      keepAlive: false,
      index:1
    },
  },
  {
    path:'/list',
    name:'list',
    component:List,
    meta: {
      keepAlive: true,
      index:2
    },
  },
  {
        path:'/approve',
        name:'approve',
        component:Approve,
        meta: {
            keepAlive: false,
            index:3
        },
    },
    {
        path:'/detailInfo',
        name:'detailInfo',
        component:DetailInfo,
        meta: {
            keepAlive: false,
            index:3
        },
    },
    {
        path:'/info',
        name:'info',
        component:Info,
        meta: {
            keepAlive: false,
            index:4
        },
    }
]

 

看到这里估计你仅仅是知道transition变量是根据页面切换to和from索引来控制值,其实这个值是一个过渡类名的前缀,用来拼接transition的过渡状态,以下引用官方的解释:

 

过渡的类名

在进入/离开的过渡中,会有 6 个 class 切换。

  1. v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。

  2. v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。

  3. v-enter-to: 2.1.8版及以上 定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。

  4. v-leave: 定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。

  5. v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。

  6. v-leave-to: 2.1.8版及以上 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。

   对于这些在过渡中切换的类名来说,如果你使用一个没有名字的 <transition>,则 v- 是这些类名的默认前缀。如果你使用了 <transition name="my-transition">,那么 v-enter 会替换为 my-transition-enter

 

以上是官方的解释,下面看看css是怎么写的:

.slide-right-enter-active,
  .slide-right-leave-active,
  .slide-left-enter-active,
  .slide-left-leave-active {
    will-change: transform;
    transition: all 500ms;
    position: absolute;
  }
  .slide-right-enter {
    opacity: 0;
    transform: translate3d(-100%, 0, 0);
  }
  .slide-right-leave-active {
    opacity: 0;
    transform: translate3d(100%, 0, 0);
  }
  .slide-left-enter {
    opacity: 0;
    transform: translate3d(100%, 0, 0);
  }
  .slide-left-leave-active {
    opacity: 0;
    transform: translate3d(-100%, 0, 0);
  }

以上就是把transition的状态写了个过渡样式,加上这样的代码,你就可以实现需求一。附上完整代码:

<template>
  <div id="app">
    <transition :name="transitionName">
      <keep-alive>
         <router-view  v-if="$route.meta.keepAlive"></router-view>
      </keep-alive>
    </transition>
    <transition :name="transitionName">
         <router-view v-if="!$route.meta.keepAlive"></router-view>
    </transition>
  </div>
</template>

<script>


  export default {
    name: 'app',
    data(){
      return {
        // text:sessionStorage.getItem('parameters')
          transitionName:''
      }
    },
      watch: {//使用watch 监听$router的变化
          $route(to, from) {
              //如果to索引大于from索引,判断为前进状态,反之则为后退状态
              if(to.meta.index > from.meta.index){
                  //设置动画名称
                  this.transitionName = 'slide-left';
              }else{
                  this.transitionName = 'slide-right';
              }
          }
      }
  }
</script>

<style lang="less">
  @import '~vux/src/styles/reset.less';

  #app{
    /*position: relative;*/
  }
  body {
    background-color: #fbf9fe;
  }
  .vux-x-icon {
    fill:#1d83ef;
  }
  .backicon {
    width:38px;
    height:38px;
    display:inline-block;
    border-radius:100%;
    border:1px solid #1d83ef;

  }
  .slide-right-enter-active,
  .slide-right-leave-active,
  .slide-left-enter-active,
  .slide-left-leave-active {
    will-change: transform;
    transition: all 500ms;
    position: absolute;
  }
  .slide-right-enter {
    opacity: 0;
    transform: translate3d(-100%, 0, 0);
  }
  .slide-right-leave-active {
    opacity: 0;
    transform: translate3d(100%, 0, 0);
  }
  .slide-left-enter {
    opacity: 0;
    transform: translate3d(100%, 0, 0);
  }
  .slide-left-leave-active {
    opacity: 0;
    transform: translate3d(-100%, 0, 0);
  }
</style>

 

注明:上周5同事发现了一个bug,发现用transition之后,切换页面的时候可能可能可能会出现一个问题:会出现短暂的白板!!!同事说,可能是加了transition左右滑动的时候定位出现的问题,所以出现短暂白板。当时的解决方案就是,在app.vue中的,给#app加了个样式,position:relative,其他的子组件每个最外层都加了个position:absolute。这样就完美解决了。不过今天写博客的时候,我又实验了一把,没出现白板的问题。如果出现以上问题,就试试加个定位吧。

另外,还有个bug,上面的代码,是通过v-if去判断缓存,而且有两个transition,运行起来发现,切换页面的时候交替闪现,其实,这里也猜到了,是两个transition通过v-if判断的时候,出现的交错的bug。下面继续完善上面的需求:

 下面是文档介绍:

include - 字符串或正则表达式。只有匹配的组件会被缓存。 
exclude - 字符串或正则表达式。任何匹配的组件都不会被缓存。

下面贴上更改后app.vue的代码:

<template>
  <div id="app">
    <transition :name="transitionName">
      <keep-alive include="list">
         <router-view></router-view>
        <!--<router-view  v-if="$route.meta.keepAlive"></router-view>-->
      </keep-alive>
    </transition>
    <!--<transition :name="transitionName">
         <router-view v-if="!$route.meta.keepAlive"></router-view>
    </transition>-->
  </div>
</template>

app.vue其他地方不变,这里引入的include(当然,如果你喜欢用exclude也可以,相反而已,排除引号内的组件名字,以外的都要缓存)是要缓存的组件name,多个缓存页面name用逗号分隔。比如:include="list,info,home"

所以路由页面的页不用设置meta:{keepAlive:true}了,路由代码如下:

export const routes = [
  {
    path:'/',
    name:'home',
    component:Home,
    meta: {
      index:1
    },
  },
  {
    path:'/list',
    name:'list',
    component:List,
    meta: {
      index:2
    },
  },
  {
        path:'/approve',
        name:'approve',
        component:Approve,
        meta: {
            index:3
        },
    },
    {
        path:'/detailInfo',
        name:'detailInfo',
        component:DetailInfo,
        meta: {
            index:3
        },
    },
    {
        path:'/info',
        name:'info',
        component:Info,
        meta: {
            index:4
        },
    }
]

 

over,这是今天的内容,自己的一份记录,也希望对你有帮助。

 

posted @ 2019-01-21 15:46  Mr.mmming  阅读(1111)  评论(0编辑  收藏  举报