18.Vue过渡&动画:transition

简介

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

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

过渡类名

在进入的过渡中,会有 3 个 class 切换。
v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。
v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
v-enter-to:进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。

离开的过渡中,会有 3 个 class 切换。
v-leave:定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
v-leave-to:离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。
在这里插入图片描述
 

单元素/组件的过渡

进入/离开效果相同的css过渡

以下便是使用transition包裹p标签实现p标签淡入淡出的例子。这里的transition使用了name=‘xxx’字段,所以默认的.v-enter被替换成了.xxx-enter,其余类名同理。

<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js"></script>
		<style type="text/css">
			.xxx-enter-active,
			.xxx-leave-active {
                /* 进入与离去的过程中opacity改变过程持续.5s */
				transition: opacity .5s;
			}

			.xxx-enter,
			.xxx-leave-to {
                /* 进入之前/离开之后opacity为0(进入之后,离开之前样式是既定的,不用定义) */
				opacity: 0;
			}
		</style>
	</head>
	<body>
		<div id="content">
			<button @click="isShow=!isShow">执行动画</button>
			<transition name="xxx">
				<p v-if="isShow">我出现了</p>
			</transition>
		</div>
	</body>
	<script>
		var vm = new Vue({
			el: '#content',
			data: {
				isShow: true
			}
		});
	</script>
</html>

运行:
在这里插入图片描述
 

进入/离开效果不同的css过渡

<style type="text/css">
/* 进入时所有效果匀速播放.5s */
.xxx-enter-active {
    transition: all .5s ease;
}

/* 离开时所有效果变速播放1s */
.xxx-leave-active {
    transition: all 1s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}

.xxx-enter,
.xxx-leave-to {
    /* 两个效果,transition后面用all */
    transform: translateX(10px);
    opacity: 0;
}
</style>

运行:
在这里插入图片描述
 

css动画

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

<style type="text/css">
.xxx-enter-active {
    /* 使用xxx-in这一变化 */
    animation: xxx-in .5s;
}

.xxx-leave-active {
    /* 使用xxx-in这一变化的反转 */
    animation: xxx-in .5s reverse;
}

/* 按照执行进度设置元素状态 */
@keyframes xxx-in {
    0% {
    	transform: scale(0);
    }
    
    50% {
    	transform: scale(1.5);
    }
    
    100% {
    	transform: scale(1);
    }
}
</style>

<body>
    <div id="content">
        <button @click="isShow=!isShow">执行动画</button>
        <transition name="xxx">
            <p v-if="isShow">我出现了11111111111111111111111111111111111111111111111</p>
        </transition>
    </div>
</body>

运行,效果正常:
在这里插入图片描述
但是如果内容较短:

<p v-if="isShow">我出现了</p>

运行效果会不正常:
在这里插入图片描述
设置样式display: inline-block可以解决此问题:

<p v-if="isShow" style="display: inline-block;">我出现了</p>

运行:
在这里插入图片描述
 

自定义过渡类名+第三方动画库

我们可以通过以下 attribute 来自定义过渡类名,他们的优先级高于普通的类名,这对于 Vue 的过渡系统和其他第三方 CSS 动画库,如 Animate.css 结合使用既方便又炫酷:

  • enter-class
  • enter-active-class
  • enter-to-class
  • leave-class
  • leave-active-class
  • leave-to-class
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js"></script>
  		<!-- 引入第三方动画库Animate.css -->
		<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
		<style type="text/css">
		</style>
	</head>
	<body>
		<div id="content">
			<button @click="isShow=!isShow">执行动画</button>
                   <!-- 使用自定义过渡的类名enter-active-class、leave-active-class -->
			<transition 
                       enter-active-class="animated tada" 
                       leave-active-class="animated bounceOutRight" 
                       name="xxx">
				<p v-if="isShow" >我出现了</p>
			</transition>
		</div>
	</body>
	<script>
		var vm = new Vue({
			el: '#content',
			data: {
				isShow: true
			}
		});
	</script>
</html>

运行:
在这里插入图片描述
 

多个元素的过渡

当有相同标签名的元素切换时,需要通过 key attribute 设置唯一的值来标记以让 Vue 区分它们。

<style type="text/css">
		.xxx-enter-active,
		.xxx-leave-active {
			transition: opacity .5s;
		}

		.xxx-enter,
		.xxx-leave-to {
			opacity: 0;
		}
	</style>
 
	<body>
		<div id="el">
			<div><button @click="isEditing=!isEditing">改一下</button></div>

                   <!-- transition 多个元素要分别加上 key -->
			<transition name="xxx">
				<button v-if="isEditing" key="save">
					Save
				</button>
				<button v-else key="edit">
					Edit
				</button>
			</transition>
		</div>
	</body>
	<script type="text/javascript">
		let vm = new Vue({
			el: "#el",
			data: {
				isEditing: true
			}
		})
	</script>

 

过渡模式

上面的例子中两个按钮都被重绘了,一个离开过渡的同时另一个开始进入过渡,这样的展示效果并不美观,对于这种情况可以设置过渡模式解决:

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

in-out效果:

<transition name="xxx" mode="in-out">...</transition>

在这里插入图片描述
out-in效果:
在这里插入图片描述
 

多个组件的过渡

多个组件的过渡不需要 key attribute,需要使用<component v-bind:is=“view”></component>动态组件。

    <style type="text/css">
     	.xxx-enter-active, .xxx-leave-active {
                  transition: opacity .3s ease;
            }
            
            .xxx-enter, .xxx-leave-to{
                  opacity: 0;
            }
    </style>
 
     <body>
		<div id="el">
			<div><button @click="changeView">改一下</button></div>

			<transition name="xxx" mode="out-in">
				<!--component + v-bind:is 作为动态组件 -->
				<component v-bind:is="viewName"></component>
			</transition>
		</div>
	</body>
	<script type="text/javascript">
		let vm = new Vue({
			el: "#el",
			data: {
				viewName: 'v-a' //放置【当前组件】的变量
			},
			components: {
				'v-a': {
					template: '<div>Component A</div>'
				},
				'v-b': {
					template: '<div>Component B</div>'
				}
			},
			methods: {
                           //改变当前展示的组件
				changeView() {
					if (this.viewName === 'v-a') {
						this.viewName = 'v-b'
					} else {
						this.viewName = 'v-a'
					}
				}
			}
		})
	</script>

运行:
在这里插入图片描述
 

列表过渡

同时渲染整个列表(比如v-for),可以使用 <transition-group> 组件。特点如下:

  • 不同于 <transition>,它会以一个真实元素呈现:默认为一个 <span>。也可以通过 tag attribute 自定义为其他元素。
  • 过渡模式不可用,因为不再相互切换特有的元素。
  • 内部元素 总是需要 提供唯一的 key 属性值。
  • CSS 过渡的类将会应用在内部的元素中,而不是这个组/容器本身。

进入/离开过渡

	<style type="text/css">
		.list-item {
			display: inline-block;
			margin-right: 10px;
		}

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

		.xxx-enter,
		.xxx-leave-to {
			opacity: 0;
			transform: translateY(30px);
		}
	</style>
 
	<body>
		<div id="el">
			<button v-on:click="add">增加一个数</button>
			<button v-on:click="remove">删除一个数</button>
			<!-- tag设置外层真实标签为<p> -->
			<transition-group name="xxx" tag="p">
				<span v-for="item in items" v-bind:key="item" class="list-item">
					{{ item }}
				</span>
			</transition-group>
		</div>
	</body>
	<script type="text/javascript">
		let vm = new Vue({
			el: "#el",
			data: {
				items: [1, 2, 3, 4, 5, 6, 7, 8, 9],
				nextNum: 10
			},
			methods: {
				randomIndex: function() {
					return Math.floor(Math.random() * this.items.length)
				},
				add: function() {
					this.items.splice(this.randomIndex(), 0, this.nextNum++)
				},
				remove: function() {
					this.items.splice(this.randomIndex(), 1)
				},
			}
		})
	</script>

运行:
在这里插入图片描述
 

排序过渡

<transition-group> 组件还有一个特殊之处。不仅可以进入和离开动画,还可以改变定位。要使用这个新功能只需了解新增的 v-move attribute,它会在元素的改变定位的过程中应用。像之前的类名一样,可以通过 name 属性来自定义前缀,也可以通过 move-class 属性手动设置。

	<style type="text/css">
        /* 使用v-move */
        .xxx-move {
            transition: transform 1s;
        }
	</style>

	<body>
		<div id="content">
			<button @click="reverseArray">反序</button>
			<div>
				<transition-group name="xxx" tag="ul">
					<li v-for="item in items" :key="item">
						{{ item }}
					</li>
				</transition-group>
			</div>
		</div>
	</body>
	<script>
		var vm = new Vue({
			el: '#content',
			data: {
				items: new Array()
			},
			methods: {
				//反转数组
				reverseArray() {
					this.items.reverse();
				}
			},
			//初始化数组
			created() {
				for (var i = 0; i < 10; i++) {
					this.items.push(i);
				}
			}
		});
	</script>

运行:
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值