我下面使用的是vue2框架

我完全按照vue2文档目录来做详解的。注意是vue2文档、注意是vue2文档、注意是vue2文档

目录

单标签或单组件的过渡

初始渲染的过渡

多个元素的过渡

多个组件的过渡

列表过渡

状态过渡



单标签或单组件的过渡


vue过度与动画:过渡就是css的transition属性,动画是animation属性

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

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

注意:行内标签如果是使用css transform属性来进行过渡和动画,是不会有效果的,css本来就是这样的,transform属性只能用于块级或行内块标签


过渡的类名、css过渡


Vue封装了transition组件,这是vue内置的,直接用这个组件标签就可以

<template>
<div>
  <!-- 通过点击按钮让p标签出现或者消失,也就是vue文档说的插入(进入)或删除(离开) -->
  <button @click="show = !show">切换</button>
  <!-- 这个是transition组件标签 -->
  <transition>
  
    <!-- 单标签/一个标签,你也可以把单标签换成单组件,原理是一样的 -->
    <p v-if="show">hello</p>
    
  </transition>
  
</div>
</template>

<script>
export default {
   name:'Item',
   data() {
    return {show: false}
  },
}
</script>

<style>
/* 在p标签插入dom之前vue自动添加.v-enter在p标签身上,这是vue给我们提供的类名 */
.v-enter{
/* 比如我让p标签在插入之前向左移动100px */
margin-left: 100px;
}

/* 在p标签插入dom之后vue自动添加.v-enter-to在p标签身上,这是vue给我们提供的类名 */
.v-enter-to{
margin-left: 0px;
}
</style>

效果如下,文字一闪而过
在这里插入图片描述
解释一下上面的例子

下面这段代码,此时的p标签还没插入到Dom中,在插入之前vue自动添加.v-enter的代码让p标签在100px处,因为标签还没插入,所以此时的p标签看不到

.v-enter{
margin-left: 100px;
}

我截了个图,这就是p标签被插入到dom中了

在这里插入图片描述

此时下面这段代码被vue自动添加到p标签,也就是说当标签一插入Dom中vue就会添加这段代码在p标签上,所以你就看到p标签一闪而过,从100px到0px

.v-enter-to{
  margin-left: 0;
}

如果我们想看到100px到0px之间的移动,那么我们就要用到css的transition属性

在上面例子中加入下面代码

在p标签中加入一个css transition属性

/*这是新加入的 */
p{
  transition: all 5s;
}

此时的效果
在这里插入图片描述
在100px到0px过渡期间vue也给我们提供了一个css类名.v-enter-active,所以你可以用.v-enter-active代替p

/*代替p标签名,效果一样*/
.v-enter-active{
  transition: all 5s;
}


还有一点需要注意:
当我把上面例子中css代码改成这样

.v-enter{
  margin-left: 100px;
}

.v-enter-to{
/*从0px改成50px*/
  margin-left: 50px;
}
 
.v-enter-active{
  transition: all 5s;
}

效果是这样的
在这里插入图片描述
可能你有些疑惑
其实是vue在移除类名时造成的,vue在给标签添加或移除类名时,过程是这样的:

  • 1.当p标签在插入前,.v-enter类名被添加到p标签中,但是此时的p标签我们看不到
  • 2.当p标签被插入时,.v-enter-to和.v-enter-active同时添加到p标签中,同时.v-entrer类名被移除
  • 3.当transition: all 5s;的时间(也就是这5秒过渡)走完之后,.venter-to和.v-enter-active这两个类名也会被移除,所以此时的p标签是没有任何css的作用的,所以p标签恢复了原位。

这个是标签的动态图片
在这里插入图片描述




当p标签消失时,如果你也需要过渡动画的话,vue也给我们提供了三个css类分别是:

在上面例子中再加入这些代码

.v-leave-active{
  transition: all 5s;
}

.v-leave{
  margin-left: 100px;
}
.v-leave-to{
  margin-left: 50px;
} 

.v-leave-active 官方文档:在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。

.v-leave 官方文档:在离开过渡被触发时立刻生效,下一帧被移除。

.v-leave-active和.v-leave是同时被添加到标签中的,但是.v-leave被添加的时间只有一帧

.v-leave-to官方文档:在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。

.v-leave-to是最后一个添加到标签中的

还有一点你要知道当你点击按钮时数据已经更新了,但是标签还没被删除,还在dom中,它要等到过渡结束才会被删除。

让我们先看一下效果:
在这里插入图片描述
红线为50px处,也就是p标签从原始位置移动了50px,那么这个.v-leave类好像并没有什么作用,我也确实找不出这个.v-leave类有什么作用


可以为<transition>添加名字,作用是你可以使用多个<transition>组件标签

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


CSS 动画(animation属性)

返回目录


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

当你使用animation属性时,就没有必要使用 .v-enter / .v-enter-to /.v-leave / .v-leave-to

/*使用以下两个即可*/
.v-enter-active {
  animation: bounce-in .5s;
}
.v-leave-active {
  animation: bounce-in .5s reverse;
}
@keyframes bounce-in {
  from {
    transform: scale(0);
  }
  to {
    transform: scale(1);
  }
}

如果你使用transition属性达不到你想要的效果,那你就用animation属性,animation比transition好用多了

比如上面那个例子 ,我是想让p标签离开时先在100px处过渡到50px处,用transition根本达不到这个效果,而用animation就能达到这个效果。

对上面例子 的css代码进行更改

/* 离开动画 */
.v-leave-active {
  animation: bounce-out 2s;
}
@keyframes bounce-out {
  from {
    margin-left: 100px;
  }
  to {
    margin-left: 50px;
  }
}


/* 进入动画 */
.v-enter-active {
  animation: bounce-in 2s;
}
@keyframes bounce-in {
  from {
    margin-left: 50px;
  }
  to {
    margin-left: 100px;
  }
}

效果如下
在这里插入图片描述
进入和离开都达到了我想要的效果,如果用transition,离开动画的效果达不到


自定义过渡的类名

返回目录


我们还可以自定义vue给我们提供的这六个类名

<div>
  <button @click="show = !show">切换</button>
  <transition
    name="组件标签名"
    enter-active-class="自定义类名:ok,可用ok代替v-enter-active"
    leave-active-class="自定义类名:is,可用is代替v-leave-active"
    enter-class=""
    enter-to-class=""
    leave-class=""
    leave-to-class=""
  >
    <p v-if="show">hello</p>
  </transition>
</div>

自定义类名还有一个作用是,我们可以因此结合第三方css动画库一起使用

我下面使用的是animate动画库,因为动画库用的是animation属性的,所以我需要用到的自定义类名只有enter-active-classleave-active-class

我使用的是vue2脚手架

在这里插入图片描述


同时使用过渡和动画

返回目录


如果你同时使用transitionanimation的话,并且它们两设置的时间也不一样,你可以用type属性决定是以transition的时间为准还是以animation的时间为准

<template>
<div>
  <button @click="show = !show">切换</button>
  <transition type="transition或tanrsform">
    <p v-if="show">hello</p>
  </transition>
</div>
</template>

<script>
export default {
  name: 'ItemTwo',
  data() {
    return {
      show:true
    }
  },
}
</script>

<style >
    @keyframes move {
      0% {
        transform: translateX(0px);
      }

      100% {
        transform: translateX(100px);
      }
    }

    .v-enter,.v-leave-to{
        margin-top: 100px;
    }

/*同时使用transition和animation,它们两的时间分别是5秒和1秒
当你设置type="animation"时,那么整个过渡和动画的时间为5秒
当你设置type="transition"时,那么整个过渡和动画的时间为1秒
如果不设置type的话,那么整个过渡和动画的时间为最长时间的那个*/
    .v-enter-active,.v-leave-active {
      animation: move 5s;
      transition: all 1s;
    }

</style>

显性的过渡持续时间

返回目录


你还可以自己设置过渡和动画的时间,那么将以你的时间为准。单位为毫秒。

<transition :duration="1000">...</transition>

你也可以定制进入和移出的持续时间:
<transition :duration="{ enter: 500, leave: 800 }">...</transition>

JavaScript 钩子

返回目录


js写法很少用,不如css写法,js和css还可以结合使用,当然如果你不想结合使用,设置一下:css="false" 即可

<template>
  <div>
    <transition
      :css="false" 
      @before-enter="beforeEnter"
      @enter="enter"
      @after-enter="afterEnter"
      @enter-cancelled="enterCancelled"

      @before-leave="beforeLeave"
      @leave="leave"
      @after-leave="afterLeave"
      @leave-cancelled="leaveCancelled"
    >
      <p v-if="show">hello</p>
    </transition>
     <button @click="show = !show">切换</button>
  </div>
</template>

<script>
export default {
  name: 'ItemTwo',
  data() {
    return {show:false}
  },
  methods: {
    // 进入

    beforeEnter(el){
      //el就是标签对象,可对标签对象进行操作
    },
    // 当与 CSS 结合使用时
    // 回调函数 done 是可选的
    enter(el, done){
      el.style.color="green"
    //done()代表着完成,不执行这个done函数,那么它就不会执行下一个afterEnter钩子函数
    },
    afterEnter(el) {
    },
    //取消过渡执行这个钩子
    enterCancelled(el){
    },

    // 离开钩子函数就不详细写了
    beforeLeave(){},
    leave(){},
    afterLeave(){},
    leaveCancelled(){}
    },
}
</script>

当只用 JavaScript 过渡的时候,在 enter 和 leave 中必须使用 done 进行回调。否则,它们将被同步调用,过渡会立即完成。

还可以结合第三方Velocity js动画库一起使用

具体请看文档,目录:vue2文档->过渡 & 动画->进入/离开 & 列表过渡->JavaScript 钩子


初始渲染的过渡

返回目录


初始渲染就是在页面刚出现或者刷新的时候实现一些过渡效果,而且默认状态肯定不能是隐藏的,否则无法使用初始渲染。

初始渲染执行的是标签插入的过渡

<transition
   <!--appear的全写是appear="true",有appear就有初始渲染-->
   appear
   <!-- 自定义类名,还可以结合第三库使用使用-->
   appear-class=""
   appear-to-class=""
   appear-active-class=""
>
</transition>

初始渲染还有自定义 JavaScript 钩子,省略了,想看可以去vue2文档查看


多个元素的过渡

返回目录


有多个元素,然后经过判断只有一个元素存在的情况

<template>
<div>
  <transition>
    <h1 v-if="show">hello</h1>
    <p v-else>hi</p>
  </transition>
  <button @click="show = !show">切换</button>
</div>
</template>

<script>
export default {
  name: 'Item',
  data() {
    return {show:true}
  },
}
</script>

<style >
.v-enter,.v-leave-to{
    margin-left: 100px;
}

.v-enter-active,.v-leave-active {
  transition: all 3s;
}
</style>

效果如下
在这里插入图片描述
如果把h1标签改成p标签,那么两个标签就相同了都是p标签,那么效果就又不一样了

<transition >
    <p v-if="show">hello</p>
    <p v-else>hi</p>
</transition>

效果如下
在这里插入图片描述
这两个标签甚至没有了过渡效果了,这是因为vue为了效率,相同标签不进行切换,只使用一个标签,只替换标签里面的内容,所以相同标签的话,就不存在标签重新插入和删除了。
解决方法:只需在标签中加入key即可

<transition >
    <p v-if="show" :key="1">hello</p>
    <p v-else :key="2">hi</p>
</transition>

效果恢复了
在这里插入图片描述
只有一个标签也是可以使用key的,但是好像没有必要


过渡模式

返回目录


还有一个问题就是,当我点击切换按钮的时候,这里两个标签的进入和离开的过渡是同时开始的(上面那张图片就是这个效果),如果我不想要这种效果呢?我想进入的标签先开始过渡或者相反效果,也是可以的,vue给我们提供了这两个属性in-out out-in可以达成这种效果

下面代码只是对上面“多个元素的过渡”的例子代码中加入mode="in-out或out-in"

<div>
 <transition mode="in-out或out-in">
    <p v-if="show" :key="1">hello</p>
    <p v-else :key="2">hi</p>
  </transition>
  <button @click="show=!show" class="ok">切换</button>
</div>

这是in-out的效果
在这里插入图片描述
新进来的标签先开始过渡,过渡完成之后,旧的标签才开始过渡


这是out-in的效果
在这里插入图片描述
旧的标签先开始过渡,过渡完成之后,新的标签才开始过渡


多个组件的过渡

返回目录


多个组件过渡就是多个组件中只能显示一个组件,只需要使用<component> 动态组件来完成即可,如需了解动态组件请点击

 <transition>
     <component :is="view"></component>
  </transition>

列表过渡

返回目录


列表过渡就是这个组件<transition-group>,如果你需要多个标签有过度效果就用它,它有几个特点:

  • 1.它和<transition>(也叫单标签或单组件过渡)不同的是<transition>不会包裹一个父标签,而<transition-group>则会包裹一个父标签,默认是<span>,但是可以通过tag属性来更改为其他标签,比如:<transition-group> tag="p"

这是<transition>

  <transition>
    <span>hello</span>
  </transition>

在这里插入图片描述


这是<transition-group>

<!--<transition-group><transition>一样也是可以使用name属性来命名的,我就不不用了-->
<!--不设置tag,默认span标签-->
<transition-group tag="p">
     <!--在标签中必须写这个key值-->
    <span v-for="item in items" :key="item" > {{ item }} </span>
</transition-group>

//js中
 data() {
    return {
      items: [1,2],
    }

包裹了一个p标签
在这里插入图片描述


  • 2.过渡模式out-in/in-out不可用,因为我们不再相互切换特有的元素
  • 3.内部元素总是需要提供唯一的 key值。
  • 4.拿上面最近那张图片做比例 ,v-enter/v-leave等等这些会添加在span标签中,而不是p标签中。官方文档:CSS 过渡的类将会应用在内部的元素中,而不是这个组/容器本身。

列表的进入/离开过渡、列表的排序过渡

返回目录


我们先来看一个用<transition-group>来做随机添加/删除列表数字的例子

<template>
<div>
     <button @click="add">增加</button>
     <button @click="remove">删除</button>
    
    <transition-group tag="p">
      <span v-for="item in items" :key="item" >{{ item }}</span>
   </transition-group>

</div>
</template>

<script>
export default {
   name:"Item",
   data() {
    return {
     items: [1,2,3,4,5,6,7,8,9],
     nextNum: 10
    }
  },
  methods: {
    add(){
      //随机数
      let nub = Math.floor(Math.random() * this.items.length)
      
      this.items.splice(nub, 0,this.nextNum++)
    },
    remove(){
      // 随机数
      let nub = Math.floor(Math.random() * this.items.length)
      
      this.items.splice(nub, 1)
    }
  },
  
}
</script>

<style>
span{
  display: inline-block;
}

.v-enter,.v-leave-to{
  transform: translateY(30px);
}

.v-enter-active, .v-leave-active{
  transition: all 1s;
}
</style>

这里的span为什么设置为行内块标签呢?

是因为我设置的过渡效果是transform,transform对行内标签无作用,只对行内块/块级标签有作用

如果我设置的过渡效果是animation(animation对行内标签是否有作用,取决于你在声明@kayfranes时里面用什么属性)或其他的属性,那么对行内标签是有作用的,那就不用把行内标签变成块级或者行内块

效果如下:
在这里插入图片描述
这个例子有个问题,当添加和移除标签的时候,周围的标签会瞬间移动到他们的新布局的位置,而不是平滑的过渡。

想要周围的标签也能够有平滑的过渡,就要使用到.v-move类名,它会在标签位置改变的过程中添加

对上面例子的css代码中加入一行代码即可

/*如果你的<transition-group name="flip">有名字,那么你的.v-move类名,得这样写.flip-move*/
.v-move{
  transition: all 1s;
}

效果如下:
在这里插入图片描述
当周围标签位置改变时,.v-move就会添加在位置改变的标签上,当标签过渡完之后位置改变的标签上的.v-move又被移除
在这里插入图片描述

但是这个例子还有一个问题,就是删除的时候,周围的标签没有过渡的效果,如果你的标签没有涉及到删除,单单使用这.v-move没有任何问题,不用再另外添加代码了,如果涉及到删除,那么就得另外添加一行代码了,看下面的例子。

在这里插入图片描述
这是vue文档的例子,不涉及删除元素,使用.v-move让标签都有过渡
在这里插入图片描述

再对上面例子的css代码更改

span{
  display: inline-block;
}

.v-enter,.v-leave-to{
  transform: translateY(30px);
}

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

/*这是新添加的一行代码*/
.v-leave-active{
  position: absolute;
}

.v-move{
  transition: all 1s;
}

效果如下
在这里插入图片描述

而.v-leave-active类中的position: absolute; ,这又是什么作用呢

我们可以先把position: absolute;注释掉看看效果
在这里插入图片描述
position: absolute; 代码的图片,删除时文字下滑和周围标签移动是同时开始的。

而把position: absolute; 注释掉的这张图片,删除时文字下滑完成之后周围的标签才开始移动到它们的位置上,没有过渡效果。

这是因为v-move的类只会在周围标签位置有改变的时候添加,删除的标签会占位过渡,过渡完之后再被删除,会导致过渡时周围的标签位置没有改变。过渡结束之后,周围的标签位置再有改变vue也不会给它们添加v-move了,所以添加position: absolute;的作用就是让删除标签脱离标准流,此时周围的标签位置就会立刻发生改变,vue就会给它们添加v-move类,而删除的标签会脱离标准流来进行过渡。这就是我们看到有position: absolute;代码的那张图片,文字下滑和周围标签移动是同时开始的原因。

使用v-move时还需要注意:想要周围的标签有过渡效果,标签不能是行内标签,只有块级标签和行内块标签才有过渡效果。这是因为vue底层实现用的是transform来实现移动的。

vue文档说v-move的原理,是基于flip思想实现的,而flip思想是非常推荐使用transform来移动标签的,这是flip官网的图片。还有列表过渡插入元素时用的也是flip思想,总之使用列表过渡时不要用行内元素就行了。
在这里插入图片描述

flip思想并不复杂

flip官网点击这里flip

这是我对flip的理解,请点击

还有一个博主对flip的概述也写的很好点这里

在这里插入图片描述
当你看到周围标签有平滑过渡时,你看到的并不是真实的标签在移动,而是克隆标签在移动
在这里插入图片描述


列表的交错过渡:这个不讲


可复用的过渡、动态过渡

这两个也不讲,感兴趣的可以去vue文档查看


状态过渡

返回目录


我上面讲的所有效果都是基于标签的,而标签里面的内容也就是数据,数据的动画效果vue并没有提供内置的组件,vue文档说可以结合第三方库来实现数据的动画效果。vue把数据的动画效果叫做状态过渡

数据的动态效果
在这里插入图片描述

vue文档提到的库有:greensock

Logo

前往低代码交流专区

更多推荐