vue-transition动画应用实践

1,181 阅读5分钟

vue提供了内置组件transition用来处理动画效果

原理: 1. 通过添加或删除css类名来处理动画效果 2. 使用内置钩子函数来控制动画,也就是通过js来控制动画

注意:当动画完成之后,vue会帮我们删除class 那么会带来两个问题: 1.我门在控制台中看动画的时候是捕获不到class类名的。 2.可以用v-if来控制动画。也就是当元素创建之后才会去执行transition动画。

使用css类名控制动画用法

transition.png

  • v-enter:定义进入过渡的开始状态
  • v-enter-to: 定义进入的结束状态
  • v-enter-active: 定义进入活动状态 [定义组件/dom进入时的持续时间和运动形式,比如定义transition,animation]
  • v-leave: 定义离开过渡的开始状态
  • v-leave-to: 定义离开的结束状态
  • v-leave-active: 定义离开活动状态 [定义组件/dom离开时的持续时间和运动形式,比如定义transition,animation]
  • 使用name属性可以自定义前缀

拿路由切换举一个例子

做一个切换路由时淡隐淡出的动画

主要逻辑

  <transition >
      <router-view ></router-view>
   </transition>
 .v-enter {
    opacity: 0;
  }
  .v-enter-to {
    opacity: 1;
  }
  .v-enter-active {
    transition: 1s;
  }

  .v-leave {
    opacity: 1;
  }
  .v-leave-to {
    opacity: 0;
  }
  .v-leave-active {
    transition: 2s;
  }

先来分析一下这个路由切换的过程 1.当组件进入的时候 设置组件进入时的开始状态(v-enter)和组件进入时的结束状态(v-enter-to) 然后设置组件进入时(开始状态和结束状态v-enter-active)的持续时间和运动形式 即当前组件进入时是淡出的效果 2.当组件离开的时候呢 设置组件离开时的开始状态(v-leave)和组件离开时的结束状态(v-leave-to) 然后设置组件离开时(开始状态和结束状态v-leave-active)的持续时间和运动形式

组件进入时的过渡状态我们设置的是1秒 组件离开时的过渡状态我们设置的是2秒

那么会造成什么问题呢? 当前路由进入的时候,要离开的那个路由还没有消失,,也就是两个路由都会出现在文档流中,会造成两个路由共存的情况

See the Pen <a href='https://codepen.io/wensiyuanseven/pen/QWjMgvg'>vue-router-demo-1</a> by 思远 (<a href='https://codepen.io/wensiyuanseven'>@wensiyuanseven</a>) on <a href='https://codepen.io'>CodePen</a>. 那这种情况我们怎么处理呢? 给路由加个定位 ``` .router{ position:absolute; top:20; left:10; } ``` See the Pen <a href='https://codepen.io/wensiyuanseven/pen/QWjMgvg'>路由淡隐淡出-定位</a> by 思远 (<a href='https://codepen.io/wensiyuanseven'>@wensiyuanseven</a>) on <a href='https://codepen.io'>CodePen</a>.

然而你发现这样还是会有问题。也就是当下一个路由进入时(1秒),要离开的路由还没消失(2秒)。

这时候两个路由会重叠在一起。这是因为离开和进入的动画是同时进行的。然而实际项目中,需求并不是这样,而是在离开的元素过渡完成之后,进入的元素在进行动画。 这时候vue提供的过渡模式就派上用场了。 先看定义

  • in-out:新元素先进行过渡,完成之后当前元素过渡离开
  • out-in:当前元素先进行过渡,完成之后新元素过渡进入

我们一般用out-in比较多

See the Pen <a href='https://codepen.io/wensiyuanseven/pen/abvyeVz'>路由-过渡模式</a> by 思远 (<a href='https://codepen.io/wensiyuanseven'>@wensiyuanseven</a>) on <a href='https://codepen.io'>CodePen</a>.

那么如果只控制路由进入时的过渡动画 ,路由离开时不添加动画,那么就会有一个路由淡出的动画,路由离开时会瞬间离开,不用添加动画

See the Pen <a href='https://codepen.io/wensiyuanseven/pen/VwvzoYe'>路由淡出动画</a> by 思远 (<a href='https://codepen.io/wensiyuanseven'>@wensiyuanseven</a>) on <a href='https://codepen.io'>CodePen</a>.

我们来做一个tab切换效果

路由往左运动的动画

 <transition name="left">
See the Pen <a href='https://codepen.io/wensiyuanseven/pen/JjYrPep'>路由从左边弹出动画</a> by 思远 (<a href='https://codepen.io/wensiyuanseven'>@wensiyuanseven</a>) on <a href='https://codepen.io'>CodePen</a>.

那当路由离开的时候需要继续往左运动 又因为 两个路由是同时运动的,所以不需要设置mode(过渡状态),而防止两个路由同时出现在文档流当中,所以需要给router-view设置定位

See the Pen <a href='https://codepen.io/wensiyuanseven/pen/PoPJYvM'>PoPJYvM</a> by 思远 (<a href='https://codepen.io/wensiyuanseven'>@wensiyuanseven</a>) on <a href='https://codepen.io'>CodePen</a>.

注意 有时候我们可以不写动画运动到的默认的位置,transition会自动帮我门去处理. 可以省略

transform: translateX(0);

那动画就可以写成


/* 路由进入时 */
.left-enter {
  transform: translateX(100%);
}

.left-enter-active {
  transition: 1s;
}

/*路由离开时*/

.left-leave-to {
  transform: translateX(-100%);
}

.left-leave-active {
  transition: 1s;
}

路由往右运动的动画

See the Pen <a href='https://codepen.io/wensiyuanseven/pen/MWaERqx'>路由往右运动的动画-连续</a> by 思远 (<a href='https://codepen.io/wensiyuanseven'>@wensiyuanseven</a>) on <a href='https://codepen.io'>CodePen</a>.

那么name值不同运动形式也不同

可以根据meta路由元存储路由的索引值来判断是向左还是向右运动【就是判断向前还是向后】,假如路由很多,也可以把路由循环出来,动态添加路由元信息。

注意点: 1.路由中如果有默认的子路由,路由元信息需要存储在子路由当中,否则,存储的信息不生效。 2.用watch监听$route需要和router-view标签同级,否则不生效。

初始化时给一个默认路由

 { path: "/", component: Foo, meta: { index: 0 } }, //因为初始化的时候路由并没有改变,所以不会有动画
See the Pen <a href='https://codepen.io/wensiyuanseven/pen/BaowbgQ'>路由切换完整动画</a> by 思远 (<a href='https://codepen.io/wensiyuanseven'>@wensiyuanseven</a>) on <a href='https://codepen.io'>CodePen</a>.

可以发现当路由切换过快时会有空白的间隙,为什么呢?可能和transition的动画机制和css动画机制有关系,比如动画曲线有关系(当动画还没有结束时被终止会出现空白) 两种办法:

第一种:在动画结束时才允许切换动画 第二种:transition过渡时间设置小一点比如0.3s(推荐)

推荐对于仅使用 JavaScript 过渡的元素添加 v-bind:css="false",Vue 会跳过 CSS 的检测。这也可以避免过渡过程中 CSS 的影响,提高性能

参考文章:segmentfault.com/a/119000001…