Vue 在插入、更新或者移除DOM 时,提供多种不同方式的应用过渡效果。包括以下方式:
- 使用vue的transition标签结合css样式完成动画
- 利用animate.css结合transition实现动画
- 利用 vue中的钩子函数实现动画
一、使用vue的transition标签结合css样式完成动画
1、给需要运动的元素加入transition标签
<transition>
需要运动的元素
</transition>
2、默认情况下如果控制了transition标签元素的显示和隐藏它会默认给这个元素加入一些class
隐藏:加入类名:
v-leave
:
定义离开过渡的开始状态
。
v-leave-active :
定义离开过渡生效时的状态。
v-leave-to :
定义离开过渡的结束状态。
显示:加入类名:
v-enter:
准备进行运动的状态(起始状态)
v-enter-active:
整个运动状态
v-enter-to:
整个运动状态(强调运动的结果,结束状态)
3、将来如果给transition设置一个name为“show”以后,将来所有的类的名称都需要改变,默认前缀为v- 如果加入了name属性,需要将v- 改为show-
示例:
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to{
opacity: 0;
}
</style>
<div id="demo">
<button v-on:click="show = !show">
Toggle
</button>
<transition name="fade">
<p v-if="show">hello</p>
</transition>
</div>
<script>
new Vue({
el: '#demo',
data: {
show: true
}
})
</script>
当插入或删除包含在
transition
组件中的元素时,Vue 将会做以下处理:
(1)自动嗅探目标元素是否应用了 CSS 过渡或动画,如果是,在恰当的时机添加/删除 CSS 类名。
(2)如果过渡组件提供了 JavaScript 钩子函数,这些钩子函数将在恰当的时机被调用。
(3)如果没有找到 JavaScript 钩子并且也没有检测到 CSS 过渡/动画,DOM 操作 (插入/删除) 在下一帧中立即执行。(注意:此指浏览器逐帧动画机制,和 Vue 的 nextTick 概念不同)
对于这些在过渡中切换的类名来说,如果使用一个没有名字的
<transition>
,则
v-
是这些类名的默认前缀。如果你使用了
<transition name=”my-transition”>
,那么
v-enter
会替换为
my-transition-enter
。
v-enter-active
和
v-leave-active
可以控制进入/离开过渡的不同的缓和曲线
二、利用animate.css结合transition实现动画
可以通过以下 attribute 来自定义过渡类名:
enter-class
enter-active-class
enter-to-class (2.1.8+)
leave-class
leave-active-class
leave-to-class (2.1.8+)
它们的优先级高于普通的类名,这对于 Vue 的过渡系统和其他第三方 CSS 动画库,如
Animate.css
结合使用十分有用。
<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
<div id="example-3">
<button @click="show = !show">
Toggle render
</button>
<transition
name="custom-classes-transition"
enter-active-class="animated tada"
leave-active-class="animated bounceOutRight"
>
<p v-if="show">
明月几时有,把酒问青天。
</p>
</transition>
</div>
<script>
new Vue({
el: '#example-3',
data: {
show: true
}
})
</script>
三、利用 vue中的钩子函数实现动画
<style>
.show {
transition: all 0.5s;
}
</style>
<div id="app">
<button @click="toggle">显示/隐藏</button><br>
<transition @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">
<div class="show" v-show="isshow">
明月几时有?把酒问青天
</div>
</transition>
</div>
<script>
new Vue({
el: '#app',
data: {
isshow: false
},
methods: {
toggle: function () {
this.isshow = !this.isshow;
},
beforeEnter: function (el) {
console.log("beforeEnter");
// 当入场之前会执行 v-enter
el.style = "padding-left:100px";
},
enter: function (el, done) {
// 当进行的过程中每执行 v-enter-active
console.log("enter");
// 为了能让代码正常进行,在设置了结束状态后必须调用一下这个元素的
// offsetHeight / offsetWeight 只是为了让动画执行
el.offsetHeight;
// 结束的状态最后写在enter中
el.style = "padding-left:0px";
// 执行done继续向下执行
done();
},
afterEnter: function (el) {
// 当执行完毕以后会执行
console.log("afterEnter");
//this.isshow = false;
}
}
})
</script>
四、综合案例
1、View代码
<div id="app">
<div class="add">
编号: <input id="id" v-color="color" v-focus type="text" v-model="id">
品牌名称: <input v-model="name" type="text">
<button @click="add">添加</button>
</div>
<div>
<table class="tb">
<tr>
<th>编号</th>
<th>品牌名称</th>
<th>创立时间</th>
<th>操作</th>
</tr>
<tr v-if="list.length <= 0">
<td colspan="4">没有品牌数据</td>
</tr>
<!--加入: key="index" 时候必须把所有参数写完整 -->
<tr v-for="(item,key,index) in list" :key="index">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.ctime | dateFrm("/")}}</td>
<!-- 使用vue来注册事件时,我们在dom元素中是看不到的 -->
<td><a href="javascript:void(0)" @click="del(item.id)">删除</a></td>
</tr>
</table>
</div>
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter ="afterEnter"
@before-leave="beforeLeave"
@leave="leave"
@after-leave ="afterLeave"
>
<div class="del" v-show="isshow">
<ul>
<li>您确定要删除当前数据吗</li>
<li>
<button @click="delById">确定</button>
<button @click="showClose">关闭</button>
</li>
</ul>
</div>
</transition>
</div>
2、
Model代码
// 使用全局过滤器(公有过滤器)
Vue.filter("dateFrm", function (time,spliceStr) {
// return "2017-11-16";
var date = new Date(time);
//得到年
var year = date.getFullYear();
// 得到月
var month = date.getMonth() + 1;
// 得到日
var day = date.getDate();
return year + spliceStr + month + spliceStr + day;
});
// 先将自定义指令定义好
// directive有两个参数
//参数一: 自定义指令 v-focus
//参数二: 对象,对象中可以添加很多方法
// 添加一个inserted方法:而这个方法中又有两个参数:
//参数一:el 当前使用自定义指令的对象
//参数二:obj 是指它(v-color="color" )后面设置的表达式
//{expression:"color",value:"red",}
Vue.directive("focus", {
inserted: function (el, obj) {
// console.log(el);
el.focus();
}
});
Vue.directive("color", {
inserted: function (el, obj) {
// obj.style.color = "red";
obj.style.color = obj.value;//????????????
console.log(obj.value);
}
});
var vm = new Vue({
el: "#app",
data: {
delId:"",// 用来将要删除数据的id进行保存
isshow:false,
color: "green",
id: 0,
name: '',
list: [
{ "id": 1, "name": "德云IT学苑", "ctime": Date() },
{ "id": 2, "name": "西安邮电大学", "ctime": Date() }
]
},
// mounted(){
// this.getFocus()
// },
methods: {
add: function () {
//将id和namepush到list数组中
this.list.push({ "id": this.id, "name": this.name, "ctime": Date() });
},
del: function (id) {
this.isshow = true;
// 将得到的id保存到delId里面
this.delId = id;
},
beforeEnter:function(el) {
el.style.left = "100%";
},
enter:function(el,done) {
el.offsetHeight;
el.style.left = "35%";
},
afterEnter:function(el){
},
beforeLeave:function(el){
el.style.left = "35%";
},
leave:function(el,done){
el.offsetHeight;
el.style.left = "100%";
setTimeout(function(){
done();
},500);
},
afterLeave:function(el){
},
showClose:function(el){
this.isshow = false;
},
delById:function() {
_this = this;
// 根据DelId删除对应的数据
var index = this.list.findIndex(function(item){
return item.id ==_this.delId;
});
this.list.splice(index,1);
// 关闭删除框
this.isshow = false;
}
}
});
3
、CSS代码
#app {
width: 600px;
margin: 10px auto;
}
.tb {
border-collapse: collapse;
width: 100%;
}
.tb th {
background-color: #0094ff;
color: white;
}
.tb td,
.tb th {
padding: 5px;
border: 1px solid black;
text-align: center;
}
.add {
padding: 5px;
border: 1px solid black;
margin-bottom: 10px;
}
.del li{
list-style: none;
padding: 10px;
}
.del{
position: absolute;
top:45%;
left: 45%;
width: 300px;
border: 1px solid rgba(0,0,0,0.2);
transition: all 0.5s;
}