Vue动画的使用

本文详细介绍了Vue中如何实现动画,包括使用过渡类名、animate.css库、钩子函数以及transition-group元素。通过实例代码展示了动画在提高用户体验方面的应用,如淡入淡出、位移效果以及半场动画等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

动画的作用:提高用户的体验,帮助用户更好的理解页面中的功能。

 

使用过渡类名实现动画

动画进入:

  • v-enter:动画进入之前的初始状态

  • v-enter-to:动画进入之后的结束状态

  • v-enter-active:动画进入的时间段

PS:第一、第二个是时间点;第三个是时间段。

动画离开:

  • v-leave:动画离开之前的初始状态

  • v-leave-to:动画离开之后的结束状态

  • v-leave-active:动画离开的时间段

PS:第一、第二个是时间点;第三个是时间段。

 

举个栗子:通过Vue的过渡类名来实现

v-enter-tov-leave的状态是一样的。而且一般来说,v-enterv-leave-to的状态也是一致的。所以,我们可以把这四个状态写成两组。

现在我们来写一段代码使得点击按钮时,让div显示/隐藏。

 

1.如果我们不使用动画,应该是这样做:

<!DOCTYPE html>
<html>
<head>
	<meta charset = "UTF-8">
	<link rel="stylesheet" type="text/css" href="index.css">
   <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
   <script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
</head>
<body>
	<div id="app">
		<input type="button" value="toggle" @click="flag=!flag">
		<!-- 需求:点击按钮,让h3显示,再点击,让h3隐藏-->
		<h3 v-if="flag">this is the h3</h3>
	</div>

	<script src="index.js"></script>
</body>
</html>
new Vue({
	el:'#app',
	data:{
		flag:false
	},
	methods:{}
})

 

2.使用动画:通过Vue的过渡类名来实现

现在,我们加淡入淡出的动画,让div显示和隐藏。

<!DOCTYPE html>
<html>
<head>
	<meta charset = "UTF-8">
	<link rel="stylesheet" type="text/css" href="index.css">
   <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
   <script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
</head>
<body>
	<div id="app">
		<input type="button" value="toggle" @click="flag=!flag">
		<!-- 需求:点击按钮,让h3显示,再点击,让h3隐藏-->
		<!-- 使用transition元素,把需要被动画控制的元素,包裹起来-->
		<!-- transition元素是VUE官方提供的-->
	<transition>
		<h3 v-if="flag">this is the h3</h3>
	</transition>
	</div>

	<script src="index.js"></script>
</body>
</html>
#app {
	width: 800px;
	margin: 20px auto;
}

.v-enter,
.v-leave-to{
	opacity: 0;
}

.v-enter-active,
.v-leave-active{
	transition: all 1s ease;
}
new Vue({
	el:'#app',
	data:{
		flag:false
	},
	methods:{}
})

我们使用vue提供的<transition>标签把需要被动画控制的元素,包裹起来;然后使用.v-enter.v-leave-to等进行动画的定义

 

 

3、再加一个tramsform属性进行位移

我们在上方代码的基础之上,加一个tramsform属性,让动画有一个位移的效果。

#app {
	width: 800px;
	margin: 20px auto;
}

.v-enter,
.v-leave-to{
	opacity: 0;
	transform: translateX(80px);/* 表示一开始让DOM元素处于靠右80px的位置*/
}

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

 

 

 

 

修改过渡类名的前缀

在上一小段中,.v-enter.v-leave-to这些过渡类名都是以v-开头的。这样做,会有一个局限性:假设有两个DOM元素都用<transition>进行了包裹,那这两个DOM元素就都具备了v-中所定义的动画。

如果我们想把两个DOM元素的动画进行分开定义,该怎么做呢?这里,我们可以通过修改过渡类名的前缀来做。比如:

第一步:(自定义别名)

	<transition name="my">
		<h3 v-if="flag">this is the h3</h3>
	</transition>

上方代码中,我们加了name="my"

第二步:(我们就可以使用 my-enter.my-leave-to这些类名了)

 .my-enter,
    .my-leave-to {
      opacity: 0;
      transform: translateY(70px);
    }

 

完整代码如下:

<!DOCTYPE html>
<html>
<head>
	<meta charset = "UTF-8">
	<link rel="stylesheet" type="text/css" href="index.css">
   <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
   <script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
</head>
<body>
	<div id="app">
		<input type="button" value="toggle" @click="flag=!flag">
		<!-- 需求:点击按钮,让h3显示,再点击,让h3隐藏-->
		<!-- 使用transition元素,把需要被动画控制的元素,包裹起来-->
		<!-- transition元素是VUE官方提供的-->
	<transition>
		<h3 v-if="flag">this is the h3</h3>
	</transition>


	<hr>

	<input type="button" value="toggle2" @click="flag2=!flag2">
	<transition name="my">
		 <h6 v-if="flag2">this is the h6</h6>
	</transition>
	</div>

	<script src="index.js"></script>
</body>
</html>
#app {
	width: 800px;
	margin: 20px auto;
}

.v-enter,
.v-leave-to {
        opacity: 0;
        transform: translateX(150px);
        }

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


.my-enter,
.my-leave-to{
	opacity: 0;
	transform: translateY(70px);
}

.my-enter-active,
.my-leave-active{
	transition: all 1s ease;
}
new Vue({
	el:'#app',
	data:{
		flag:false,
		flag2:false
	},
	methods:{}
})

 

 

使用第三方animate.css类库实现动画

下面的代码中,我们使用animate.css提供的bounceInbounceOut这两个类来做入场、离场的动画。代码如下:

<!DOCTYPE html>
<html>
<head>
	<meta charset = "UTF-8">
	<link rel="stylesheet" type="text/css" href="animate.css">
   <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
   <script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
</head>
<body>
	<div id="app">
		<input type="button" value="toggle" @click="flag=!flag">
		<!-- 需求:点击按钮,让h3显示,再点击,让h3隐藏-->
		<!-- 使用transition元素,把需要被动画控制的元素,包裹起来-->
		<!-- transition元素是VUE官方提供的-->
	<transition enter-active-class="animated bounceIn" leave-active-class="animated bounceOut">
		<h3 v-if="flag">this is the h3</h3>
	</transition>


	<hr>

	<input type="button" value="toggle2" @click="flag2=!flag2">
	<transition name="my">
		 <h6 v-if="flag2">this is the h6</h6>
	</transition>
	</div>

	<script src="index.js"></script>
</body>
</html>
new Vue({
	el:'#app',
	data:{
		flag:false,
	},
	methods:{}
})

 

上面的代码中,注意:

注意1:enter-active-classleave-active-class这两个类名是Vue动画里的关键词,不能写成自己随意起的类名。

注意2:bounceInbounceOut这两个类不能直接使用,要在前面加上animated这个类;否则动画是不会生效的。当然,上面的代码中,我们还可以把class = animated这个代码移到<h3>标签里,效果是一样的,如下:

<!-- 需求: 点击按钮,让 h3 显示,再点击,让 h3 隐藏 -->
        <transition enter-active-class="bounceIn" leave-active-class="bounceOut">
            <h3 v-if="flag" class="animated">this is the H3</h3>
        </transition>

 

我们把上面的代码改进一下,如果我们想给入场、出场动画设置持续的时间,可以使用:duration来做。

分别设置入场、出场动画的持续时间:

<div id="app">
		<input type="button" value="toggle" @click="flag=!flag">
		<!-- 需求:点击按钮,让h3显示,再点击,让h3隐藏-->
		<!-- 使用transition元素,把需要被动画控制的元素,包裹起来-->
		<!-- transition元素是VUE官方提供的-->
	<transition enter-active-class="animated bounceIn" leave-active-class="animated bounceOut" :duration="{enter:1000,leave:500}">
		<h3 v-if="flag">this is the h3</h3>
	</transition>
	</div>

 

 

钩子函数实现半场动画

只有出场动画、没有离场动画,这种就是属于半场动画。比如你把一件商品加入收藏,会出现一个动画;当再次点击收藏按钮的时候却看不到动画效果,这就说明,只有前一半才有动画。

半场动画,可以使用钩子函数来实现。

 

动画的钩子函数介绍

可以在属性中声明 JavaScript 钩子函数:(这八个钩子函数可以理解成是动画的生命周期)

<transition
  v-on:before-enter="beforeEnter"
  v-on:enter="enter"
  v-on:after-enter="afterEnter"
  v-on:enter-cancelled="enterCancelled"

  v-on:before-leave="beforeLeave"
  v-on:leave="leave"
  v-on:after-leave="afterLeave"
  v-on:leave-cancelled="leaveCancelled"
>
  <!-- DOM元素 -->
</transition>

我们可以这样理解:上面这八个钩子函数(四个入场、四个离场),对应了八个事件,我们要紧接着在methods中定义八个函数。

如果要定义半场动画,做法是:直接在methods中写入场动画的函数,不写离场动画的函数即可。

 

 

举个栗子:

使用钩子函数模拟小球半场动画

现在要实现的例子是:点击按钮后,让小球进行移动。完整代码如下:

<!DOCTYPE html>
<html>
<head>
	<meta charset = "UTF-8">
	<link rel="stylesheet" type="text/css" href="index.css">
   <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
   <script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
</head>
<body>
	<div id="app">
		<input type="button" value="加入购物车" @click="flag=!flag">
	<transition @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">
		<div class="ball" v-show="flag"></div>
	</transition>
	</div>
	<script src="index.js"></script>
</body>
</html>

 

#app {
	width: 800px;
	margin: 20px auto;
}

.ball{
	width: 15px;
	height: 15px;
	border-radius: 50%;
	background-color: red;
}
new Vue({
	el:'#app',
	data:{
		flag:false,
	},
	methods:{
		beforeEnter(el){
			//beforeEnter 表示动画入场之前,可以在beforeEnter中设置元素在动画开始前的起始样式
			//设置小球开始动画之前的起始位置
			el.style.transform = "translate(0,0)"
		},
		enter(el,done){
			//注意!el.offsetWidth这句话没有实际作用,但是如果不写,就没有动画效果。可以认为el.offsetWidth会强制动画刷新
			el.offsetWidth
			//enter表示动画开始之后的样式,这里,可以设置小球完成动画之后的结束状态
			el.style.transform = "translate(150px,300px)"
			el.style.transition = "all 1s ease"

			//注意!这里的done,其实就是afterEnter这个函数
			done()
		},

		afterEnter(el){
			//动画完成之后,会调用afterEnter
			this.flag = !this.flag
			//因为最开始的时候,小球就是处于消失的状态,这行代码可以让小球的动画重新开始
		}

	}
})

 

 

上面的代码中,有两个地方要注意:

注意1

el.offsetWidth这行代码不能少。虽然这行代码没有实际的意义,但是少了之后,动画效果出不来。

当然,我们也可以把这行代码换成el.offsetHeightel.offsetLeftel.offsetTop之类的,只要包含了offset就行。

注意2

enter()函数里,函数的第二个参数要加上done,函数体的最后一行要写done(),表示立即执行后面的afterEnter()函数;如果没有这个done,则会延迟执行后面的afterEnter()函数。

 

 

使用transition-group元素实现列表动画

现在的场景是:在一个<ul>列表中,如果我想给指定的某个li添加动画效果,该怎么做呢?(需要声明的是,这些li是用v-for循环进行遍历的)

如果我们用<transition>li包裹起来,就会让所有的li都具备了动画,这显然是不可取的。

那该怎么做呢?这里我们就可以用transition-group进行包裹。

 

1.点击添加按钮后,给新增的 item 加个动画

<!DOCTYPE html>
<html>
<head>
	<meta charset = "UTF-8">
	<link rel="stylesheet" type="text/css" href="index.css">
   <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
   <script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
</head>
<body>
	<div id="app">
		<div>
			<label>
				Id:
				<input type="text" v-model="id">
			</label>

			<label>
				Name:
				<input type="text" v-model="name">
			</label>

			<input type="button" value="添加" @click="add">
		</div>

		<transition-group>
			<li v-for="(item,i) in list"  :key="item.id">
				{{item.id}} --- {{item.name}}
			</li>
		</transition-group>
	</div>
	<script src="index.js"></script>
</body>
</html>
#app {
	width: 800px;
	margin: 20px auto;
}

li{
	border: 1px dashed #999;
	margin: 5px;
	line-height: 35px;
	padding-left: 5px;
	font-size: 12px;
	width: 100%;
}

li:hover{
	background-color: hotpink;
	transition: all 0.8s ease;
}

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

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

 

new Vue({
	el:'#app',
	data:{
		id:'',
		name:'',
		list:[
		{id:1,name:'刘备'},
		{id:2,name:'关羽'},
		{id:3,name:'张飞'},
		{id:4,name:'赵云'},
		]
	},
	methods:{
		add(){
			this.list.push({id:this.id,name:this.name})
			this.id = this.name = ''

		}
	}
})

效果:

 

改进1:添加删除item的功能

基于上面的代码,我们来添加删除item的功能,代码本应该是这样写:

<!DOCTYPE html>
<html>
<head>
	<meta charset = "UTF-8">
	<link rel="stylesheet" type="text/css" href="index.css">
   <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
   <script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
</head>
<body>
	<div id="app">
		<div>
			<label>
				Id:
				<input type="text" v-model="id">
			</label>

			<label>
				Name:
				<input type="text" v-model="name">
			</label>

			<input type="button" value="添加" @click="add" >
		</div>

		<transition-group>
			<li v-for="(item,i) in list"  :key="item.id" @click="del(i)">
				{{item.id}} --- {{item.name}}
			</li>
		</transition-group>
	</div>
	<script src="index.js"></script>
</body>
</html>

 

new Vue({
	el:'#app',
	data:{
		id:'',
		name:'',
		list:[
		{id:1,name:'刘备'},
		{id:2,name:'关羽'},
		{id:3,name:'张飞'},
		{id:4,name:'赵云'},
		]
	},
	methods:{
		add(){
			this.list.push({id:this.id,name:this.name})
			this.id = this.name = ''

		},

		del(i){
			this.list.splice(i,1);
		}
	}
})

 

 

改进2:

上图中,我们发现,当我删除第2个item时,第3、第4个item在往上移动的过程比会较突兀。为了改进这个地方,我们可以给.v-move.v-leave-active加一些动画属性。

.v-move{
	transition: all 0.6s ease;
}

.v-leave-active{
	position: absolute;
}

 

transition-group中appear和tag属性的作用

我们可以在上面的代码基础之上,给transition-group加上appear属性,这样的话,可以让transition-group包裹的所有DOM元素在刷新时,有淡入效果

<!DOCTYPE html>
<html>
<head>
	<meta charset = "UTF-8">
	<link rel="stylesheet" type="text/css" href="index.css">
   <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
   <script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
</head>
<body>
	<div id="app">
		<div>
			<label>
				Id:
				<input type="text" v-model="id">
			</label>

			<label>
				Name:
				<input type="text" v-model="name">
			</label>

			<input type="button" value="添加" @click="add" >
		</div>

			<!-- 给 ransition-group 添加 appear 属性,实现页面刚展示出来时候,入场时候的效果 -->
            <!-- 通过 为 transition-group 元素,设置 tag 属性,指定 transition-group 渲染为指定的元素,如果不指定 tag 属性,默认,渲染为 span 标签 -->
            <transition-group appear>
			<li v-for="(item,i) in list"  :key="item.id" @click="del(i)">
				{{item.id}} --- {{item.name}}
			</li>
		</transition-group>
	</div>
	<script src="index.js"></script>
</body>
</html>

 

 

改进transition-grouptag属性

上面的代码中,我们审查一下代码元素会发现,用transition-group包裹的元素,会被默认套上一层<span>

 

 

这个<span>虽然没有太大副作用,但是不符合代码规范。为了解决这个问题,我们可以通过tag属性给transition-group包谷的元素套上一层<ul>,然后把现有的<ul>注释掉,就可以了。最终代码如下:

 

<transition-group appear tag="ul">
            <li v-for="(item, i) in list" :key="item.id" @click="del(i)">
                {{item.id}} --- {{item.name}}
            </li>
        </transition-group>

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值