Vue学习—深入剖析单元素过渡
发布日期:2021-05-08 04:58:07 浏览次数:20 分类:原创文章

本文共 10399 字,大约阅读时间需要 34 分钟。

单元素过渡

一、单元素过渡

Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。

1.单元素/组件的过渡

Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加进入/离开过渡

  • 条件渲染 (使用 v-if)
  • 条件展示 (使用 v-show)
  • 动态组件
  • 组件根节点

2.过渡的类名

在进入/离开的过渡中,会有 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
定义离开过渡生效时的状态。
在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。
这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。

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

在这里插入图片描述

<template>  <div class="demo">    <button @click="show = !show">click</button>    <transition>      <div  class="box" v-show="show">hellow world</div>    </transition>  </div></template><script>export default {      data(){        return {          show: true    }  }}</script><style scoped>button {      margin-bottom: 10px;}.box {      width: 100px;  height: 100px;  line-height: 100px;  text-align: center;  border: 1px solid red;  color: red;}.v-enter {      opacity: 0;  transform: translateX(250px);}.v-enter-active {      transition: all 0.8s;}.v-enter-to {      opacity: 1;  transform: translateX(0px);}.v-leave {      opacity: 1;  transform: translateX(0px);}.v-leave-active {      transition: all 0.8s;}.v-leave-to {      opacity: 0;  transform: translateX(250px);}</style>

在这里插入图片描述
在这里插入图片描述

3.类名前缀

  1. transition 无 name 特性
    类名前缀为 v-。
.v-enter {     opacity: 0;  transform: translateX(250px);}.v-enter-active {     transition: all 0.8s;}.v-enter-to {     opacity: 1;  transform: translateX(0px);}.v-leave {     opacity: 1;  transform: translateX(0px);}.v-leave-active {     transition: all 0.8s;}.v-leave-to {     opacity: 0;  transform: translateX(250px);}
  1. transition 有 name 特性
    如 name 为 fade,则类名前缀为fade-。
<template>  <div class="demo">    <button @click="show = !show">click</button>    <transition name="box1">      <div class="box" v-if="show">hello world</div>    </transition>    <transition name="box2">      <div class="box" v-if="show">hello world</div>    </transition>  </div></template><script>export default {     data () {       return {         show: true,    }  }}</script><style scoped>button {     margin-bottom: 10px;}.box {     width: 100px;  height: 100px;  margin-bottom: 10px;  line-height: 100px;  text-align: center;  border: 1px solid red;  color: red;}/* 合并代码,减少耦合和代码量 */.box1-enter,.box1-leave-to {     opacity: 0;  transform: translateX(200px);}.box1-enter-active,.box1-leave-active {     transition: all .3s;}.box1-enter-to,.box1-leave {     opacity: 1;  transform: translateX(0px);}.box2-enter-to,.box2-leave {     opacity: 1;  transform: translateY(0px);}.box2-enter-active,.box2-leave-active {     transition: all .3s;}.box2-enter,.box2-leave-to {     opacity: 0;  transform: translateY(200px);}</style>

在这里插入图片描述
在这里插入图片描述

4.CSS 动画

CSS 动画用法同 CSS 过渡,区别是在动画中 v-enter 类名在节点插入 DOM 后不会立即删除,而是在 animationend 事件触发时删除。

<template>  <div class="demo">    <button @click="show = !show">click</button>    <transition>      <div class="box" v-if="show">hello world</div>    </transition>  </div></template><script>export default {     data () {       return {         show: true,    }  }}</script><style scoped>button {     margin-bottom: 10px;}.box {     width: 100px;  height: 100px;  margin-bottom: 10px;  line-height: 100px;  text-align: center;  border: 1px solid red;  color: red;}.v-enter-active {     animation: animate 1s;}.v-leave-active {     animation: animate 1s reverse;}@keyframes animate {     0% {       opacity: 0;    transform: translateX(400px) scale(1);  }  50% {       opacity: .5;    transform: translateX(200px) scale(1.5);  }  100% {       opacity: 1;    transform: translateX(0) scale(1);  }}</style>

在这里插入图片描述
在这里插入图片描述

5.自定义过渡的类名

我们可以通过以下 attribute 来自定义过渡类名:

  • enter-class
  • enter-active-class
  • enter-to-class (2.1.8+)
  • leave-class
  • leave-active-class
  • leave-to-class (2.1.8+)
<template>  <div class="demo">    <button @click="show = !show">click</button>    <transition enter-active-class="enter" leave-active-class="leave">      <div class="box" v-if="show">hello world</div>    </transition>  </div></template><script>export default {     data () {       return {         show: true,    }  }}</script><style scoped>button {     margin-bottom: 10px;}.box {     width: 100px;  height: 100px;  margin-bottom: 10px;  line-height: 100px;  text-align: center;  border: 1px solid red;  color: red;}.enter {     animation: animate 1s;}.leave {     animation: animate 1s reverse;}@keyframes animate {     0% {       opacity: 0;    transform: translateX(400px) scale(1);  }  50% {       opacity: .5;    transform: translateX(200px) scale(1.5);  }  100% {       opacity: 1;    transform: translateX(0) scale(1);  }}</style>

他们的优先级高于普通的类名,这对于 Vue 的过渡系统和其他第三方 CSS 动画库(如 Animate.css)结合使用十分有用。
由于我们不会愿意花太多时间去写一个好的动画,那么通过命名就能对各样动画进行命名。

下面推荐一款动画的css
Animate.css 官网地址:https://daneden.github.io/animate.css/
安装方式:npm install animate.css --save,最后引入css
在这里插入图片描述

<template>  <div class="demo">    <button @click="show = !show">click</button>    <transition     enter-active-class="animated bounceInRight"    leave-active-class="animated bounceOutDown">      <div class="box" v-if="show">hello world</div>    </transition>  </div></template>

6.同时使用过渡和动画

可使用 type 属性,来声明需要 Vue 监听的类型,type值可为 animation 或 transition 。

当不设置type时,默认会取 transitioned 和 animationed 两者更长的为结束时刻。(以哪个为主)

<template>  <div class="demo">    <button @click="show = !show">click</button>    <transition      type="animation"      enter-active-class="animated tada v-enter-active"      leave-active-class="animated tada v-leave-active"    >      <div class="box" v-if="show">hello world</div>    </transition>  </div></template><script>export default {     data () {       return {         show: true,    }  }}</script><style scoped>button {     margin-bottom: 10px;}.box {     width: 100px;  height: 100px;  margin-bottom: 10px;  line-height: 100px;  text-align: center;  border: 1px solid red;  color: red;}.v-enter,.v-leave-to {     opacity: 0;}.v-enter-active,.v-leave-active {     transition: all 5s;}.v-enter-to,.v-leave {     opacity: 1;}</style>

7.显性的过渡时间

在一些情况下,Vue可以自动得出过渡效果的完成时机,从而对dom进行处理。

但是有些时候,我们会设置一系列的过渡效果,例如嵌套元素也有过渡动效,其过渡效果的时间长于父元素。此时我们可以设置duration属性,定制一个显性的过渡持续时间(以毫秒记):

<transition :duration="1000">...</transition><transition :duration="{ enter:400,leave:600 }">...</transition>

也可以定制进入和移出的持续时间:

<transition :duration="{ enter: 500, leave: 800 }">...</transition>

8.初始渲染的过渡

可以通过 appear attribute 设置节点在初始渲染的过渡。

和进入/离开过渡一样,同样也可以自定义 CSS 类名。如:

appear-class="appear-enter"appear-active-class="appear-enter-active"appear-to-class="appear-enter-to"<template>  <div class="demo">    <button @click="show = !show">click</button>    <transition      :duration="1000"      appear    //进入就显示      appear-active-class="animated swing"      enter-active-class="animated tada"      leave-active-class="animated tada"    >      <div class="box" v-if="show">hello world</div>    </transition>  </div></template>

9.JavaScript 钩子

可以在属性中声明 JavaScript 钩子:

<transition  @before-enter="beforeEnter"  //入场前  @enter="enter"  //中  @after-enter="afterEnter"  //后  @enter-cancelled="enterCancelled"    //取消,用的很少  @before-leave="beforeLeave"  @leave="leave"  @after-leave="afterLeave"  @leave-cancelled="leaveCancelled">  <!-- ... --></transition>
<template>  <div class="demo">    <button @click="show = !show">click</button>    <transition      :css="false"      @before-enter="beforeEnter"      @enter="enter"      @after-enter="afterEnter"      @enter-cancelled="enterCancelled"    >      <div class="box" v-if="show">hello world</div>    </transition>  </div></template><script>export default {     data () {       return {         show: true,      x: 200,    }  },  methods: {       beforeEnter (el) {         el.style.transform = 'translateX(200px)';    },    enter (el, done) {         //done.canceled = true;//一旦动画取消,就会执行enterCancelled函数      const timer = setInterval(() => {           this.x -= 2;        el.style.transform = `translateX(${     this.x}px)`;        if(this.x <= 0) {             clearInterval(timer);          done();//done不执行,after就不会执行        }      }, 10)    },    afterEnter () {         this.x = 200;    },    enterCancelled: function () {         // console.log('cancel');      // this.isCancel = true;    }  }}</script><style scoped>button {     margin-bottom: 10px;}.box {     width: 100px;  height: 100px;  margin-bottom: 10px;  line-height: 100px;  text-align: center;  border: 1px solid red;  color: red;}</style>
  • before-enter 动画入场前,可以在其中设置元素开始动画之前的起始样式
  • enter 动画入场中,可以在其中写动画
  • after-enter 动画完成后
  • enter-cancelled 取消动画

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

设置了 appear 特性的 transition 组件,也存在自定义 JavaScript 钩子:

<transition  appear  v-on:before-appear="customBeforeAppearHook"  v-on:appear="customAppearHook"  v-on:after-appear="customAfterAppearHook"  v-on:appear-cancelled="customAppearCancelledHook">  <!-- ... --></transition>

结合 Velocity.js
继续懒,所以有了js的动画插件
Velocity.js 官网地址:http://velocityjs.org/
安装方式: npm install velocity-animate

<template>  <div class="demo">    <button @click="show = !show">click</button>    <transition      :css="false"      @before-enter="beforeEnter"      @enter="enter"      @before-leave="beforeLeave"      @leave="leave"    >      <div class="box" v-if="show">hello world</div>    </transition>  </div></template><script>export default {     data () {       return {         show: true,    }  },  methods: {       beforeEnter (el) {         el.style.opacity = 0;    },    enter (el, done) {         Velocity(el, {    opacity: 1}, {    duration: 500});      Velocity(el, {    rotateZ: 10 }, {    duration: 300 });      Velocity(el, {    rotateZ: -10 }, {    duration: 300 });      Velocity(el, {    rotateZ: 0 }, {    duration: 300, complete: done });    },    beforeLeave (el) {         el.style.transformOrigin = 'left';    },    leave (el, done) {         Velocity(el, {    translateX: '15px', rotateZ: '50deg'}, {    duration: 600});      Velocity(el, {    rotateZ: '100deg'}, {    duration: 600, loop: 2});      Velocity(el, {    rotateZ: '45deg', translateY: '30px', translateX: '30px', opacity: 0}, {    complete: done});    },  }}</script><style scoped>button {     margin-bottom: 10px;}.box {     width: 200px;  margin-bottom: 10px;  text-align: center;  border: 1px solid red;  color: red;}</style>
上一篇:Vue学习—深入剖析多元素过渡
下一篇:Vue学习—深入剖析函数式组件

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2025年04月16日 16时58分52秒