一.js钩子
(1).基础
在transition上加入@before-enter/@enter/@after-enter =“xx”即可实现Js钩子
<div id="root">
<transition @before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter">
<div v-if="show">helloWord</div>
</transition>
<button @click="handleBtnClick">click</button>
</div>
<script>
let vm = new Vue({
el:"#root",
data:{
show:true
},
methods:{
handleBtnClick(){
this.show = !this.show
},
beforeEnter(el){
el.style.color='red'
},
enter(el,done){
setTimeout(()=>{
el.style.color="green"
done();
},2000)
},
afterEnter(el){
setTimeout(()=>{
el.style.color="black"
},2000)
}
}
})
退出改为leave即可,只有enter/leave才会接收两个参数,done用来结束enter/enter
(2).使用库Velocity.js
在响应方法中使用Velocity(el,{opacity:1},{duration:1000,complete:done})实现
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.5.0/velocity.min.js"></script>
</head>
<body>
<div id="root">
<transition @before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@before-leave="beforeLeave"
@leave="leave"
@after-leave="afterLeave">
<div v-if="show">helloWord</div>
</transition>
<button @click="handleBtnClick">click</button>
</div>
<script>
let vm = new Vue({
el:"#root",
data:{
show:true
},
methods:{
handleBtnClick(){
this.show = !this.show
},
beforeEnter(el){
el.style.opacity=0;
},
enter(el,done){
Velocity(el,{
opacity:1
},{
duration:1000,
compelete:done
})
},
afterEnter(el){
},
beforeLeave(el){
},
leave(el,done){
Velocity(el,{
opacity:0
},{
duration:1000,
compelete:done
})
},
afterLeave(el){
}
}
})
</script>
二.多元素组件
(1).在transition标签中通过if else实现基本切换动画
<style>
.v-enter,
.v-leave-to{
opacity: 0;
}
.v-enter-active,
.v-leave-active{
transition: opacity 3s linear;
}
</style>
</head>
<body>
<div id="root">
<transition>
<div v-if="show">helloWord</div>
<p v-else>Bye</p>
</transition>
<button @click="handleBtnClick">click</button>
</div>
<script>
let vm = new Vue({
el:"#root",
data:{
show:true
},
methods:{
handleBtnClick(){
this.show = !this.show
}
}
})
</script>
(2).key=""解决相同元素动画失效
<transition>
<div v-if="show">helloWord</div>
<div v-else>Bye</div>
</transition>
<transition>
<div v-if="show" key="hello">helloWord</div>
<div v-else key="bye">Bye</div>
</transition>
(3).按钮On Off切换
<style>
.wrapper{
position: relative;
width: 31px;
height: 22px;
}
button{
position: absolute;
top: 0;
left: 0;
}
.v-enter,
.v-leave-to{
opacity: 0;
}
.v-enter-active,
.v-leave-active{
transition: opacity 1s linear;
}
</style>
</head>
<body>
<div id="root">
<div class="wrapper">
<transition>
<button v-if="show" key="on" @click="onClick">on</button>
<button v-else key="off" @click="onClick">off</button>
</transition>
</div>
</div>
<script>
let vm = new Vue({
el:"#root",
data:{
show:true
},
methods:{
onClick(){
this.show = !this.show
}
}
})
</script>
(4).按钮On Off切换升级版本
<style>
.wrapper{
position: relative;
width: 31px;
height: 22px;
}
button{
position: absolute;
top: 0;
left: 0;
}
.v-enter{
transform: translateX(31px);
}
.v-leave-to{
transform: translateX(-31px);
}
.v-enter-active,
.v-leave-active{
transition: all 1s linear;
}
</style>
</head>
<body>
<div id="root">
<div class="wrapper" mode="out-in">
<transition>
<button v-if="show" key="on" @click="onClick">on</button>
<button v-else key="off" @click="onClick">off</button>
</transition>
</div>
</div>
<script>
let vm = new Vue({
el:"#root",
data:{
show:true
},
methods:{
onClick(){
this.show = !this.show
}
}
})
</script>
其中如果在transition标签上加入 mode=“out-in/in-out”属性即先将out执行完再执行In,如果不加同时触发
(5).两个组件的过渡
通过component :is标签嵌套再transition标签中完成
<style>
.v-enter,
.v-leave-to{
opacity: 0;
}
.v-enter-active,
.v-leave-active{
transition: opacity 1s linear;
}
</style>
</head>
<body>
<div id="root">
<div class="wrapper">
<transition mode="out-in">
<component :is="type"></component>
</transition>
<button @click="onClick">click</button>
</div>
</div>
<script>
Vue.component('child-one',{
template:'<div>One</div>'
})
Vue.component('child-two',{
template:'<div>Two</div>'
})
let vm = new Vue({
el:"#root",
data:{
type:'child-one'
},
methods:{
onClick(){
this.type = (this.type === 'child-one' ? 'child-two': 'child-one');
}
}
})
</script>
三.列表过渡
在一个transition中同时存在多个相同标签,既要用<transition-group>标签
(1).要求在列表添加的过程中加过渡
<style>
.v-enter,
.v-leave-to{
opacity: 0;
}
.v-enter-active,
.v-leave-active{
transition: opacity 1s linear;
}
</style>
</head>
<body>
<div id="root">
<div class="wrapper">
<ul>
<transition-group mode="out-in">
<li v-for="item of list" :key="item.id">{{item.text}}</li>
</transition-group>
</ul>
<button @click="onClick">click</button>
</div>
</div>
<script>
let count = 0;
let vm = new Vue({
el:"#root",
data:{
list:[]
},
methods:{
onClick(){
this.list.push({
text:'123',
id:count++
})
}
}
})
</script>
做的事情其实就是给每个li上面添加了一个transition
四.动画封装
(1).封装
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.5.0/velocity.min.js"></script>
</head>
<body>
<div id="root">
<fade :show="show">
<div>HElloWorld</div>
</fade>
<button @click="onClick">click</button>
</div>
<script>
Vue.component('fade',{
props:['show'],
template:`
<transition name="fade"
@beforeEnter="beforeEnter"
@enter="enter"
@afterEnter="afterEnter"
@beforeLeave="beforeLeave"
@leave="leave"
@afterLeave="afterLeave">
<slot v-if="show"></slot>
</transition>
`,
methods:{
beforeEnter(el){
el.style.opacity=0;
},
enter(el,done){
Velocity(el,{
opacity:1
},{
duration:1000,
templete:done
})
},
afterEnter(el){
},
beforeLeave(el){
},
leave(el,done){
Velocity(el,{
opacity:0
},{
duration:1000,
templete:done
})
},
afterLeave(el){
}
}
})
let vm = new Vue({
el:"#root",
data:{
show:true
},
methods:{
onClick(){
this.show = !this.show
}
}
})
</script>