1、多个元素之间切换动画
多元素过渡,就是利用v-if
或者v-show
等指令,切换元素的显示,需要显示的元素就会有入场动画,需要隐藏的就有出场动画。
<template>
<div class="about">
<transition name="fade">
<div v-if="isShow" key="enter">v-if显示动画dom元素</div>
<div v-else key="out">v-else显示的动画元素</div>
</transition>
<button @click="change">点击切换</button>
</div>
</template>
<script>
export default {
data(){
return {
isShow:true,
}
},
methods:{
change(){
this.isShow = !this.isShow;
}
}
};
</script>
<style scoped>
div {
font-size: 30px;
font-weight: bold;
opacity: 1;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
.fade-enter-active,
.fade-leave-active {
transition: all 3s;
}
</style>
1.1、注意事项
在vue中存在着dom复用的机制,就是为了提升效率,在两个相同的div标签中,如果不加key,只会看到单纯的内容改变,样式不会发生任何变化。
1、当有相同标签名的元素切换时,需要通过key属性设置唯一的值来标记以让Vue区分它们
2、key属性的用处:主要是为了不让dom元素复用
3、DOM元素复用是Vue提升性能的手段,但是因为DOM元素复用,因而会导致没有任何动画效果
4、设置key属性不让它复用
2、设置动画的出场先后顺序
默认的是出场和入场的动画先后是同时进行
的!同时生效的进入和离开的过渡不能满足所有要求,因此Vue提供了过渡模式。
1、Vue在transition标签上提供了一个mode属性,来设置出场入场动画的先后顺序
2、mode的属性值为in-out,则为先执行入场动画,等入场动画执行完毕后再执行出场动画
3、mode属性值为out-in,则先执行出场动画,再执行入场动画
<template>
<div class="about">
<transition name="fade" mode="in-out">
<div v-if="isShow" key="domo">入场显示动画dom元素</div>
<div v-else key="dom">出场显示的动画元素</div>
</transition>
<button @click="change">点击切换</button>
</div>
</template>
<script>
export default {
data(){
return {
isShow:true,
}
},
methods:{
change(){
this.isShow = !this.isShow;
}
}
};
</script>
<style scoped>
div {
font-size: 30px;
font-weight: bold;
opacity: 1;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
.fade-enter-active,
.fade-leave-active {
transition: all 3s;
}
</style>
3、Vue中组件之间的动画
3.1、不利用动态组件
<template>
<div class="about">
<transition name="fade">
<childA v-if="isShow"></childA>
<childB v-else></childB>
</transition>
<button @click="change">点击切换</button>
</div>
</template>
<script>
import childA from "@/components/childA"
import childB from "@/components/childB"
export default {
data(){
return {
isShow:true,
}
},
components:{
childA,
childB
},
methods:{
change(){
this.isShow = !this.isShow;
}
}
};
</script>
<style scoped>
.fade-enter,.fade-leave-to{
opacity:0
}
.fade-enter-active,.fade-leave-active{
transition: opacity 1s;
}
</style>
3.2、利用动态组件切换
<template>
<div class="about">
<transition name="fade" mode="out-in">
<component :is="type"></component>
</transition>
<button @click="handleChange">点击切换</button>
</div>
</template>
<script>
import childA from "@/components/childA";
import childB from "@/components/childB";
export default {
data() {
return {
type: "childA",
};
},
components: {
childA,
childB,
},
methods: {
handleChange() {
this.type = this.type == "childA" ? "childB" : "childA";
},
},
};
</script>
<style scoped>
.fade-enter,
.fade-leave-to {
opacity: 0;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 1s;
}
</style>
4、Vue中的列表过渡
对于过渡有如下:
1、单个节点
2、同一时间渲染多个节点中的一个
如何同时渲染整个列表,达到同等的v-for
效果,这个时候就要使用<transition-group>组件
特点:
1、<transition>
标签会以一个真实的元素呈现,默认的是<span>
。也可以通过tag属性,更换为其他元素
2、过渡模式不可用(上面说到的mode
),因为我们不再相互切换特定的元素
3、内部元素总是需要提供唯一的key
属性值
4、CSS过渡的类将会应用在内部的元素中,而不是这个容器本身
4.1、使用<transition-group>
标签嵌套
<template>
<div class="about">
<transition-group name=demo>
<div v-for="item in list" :key="item.id">
{{ item.name }}
</div>
</transition-group>
<button @click="handleChange">点击切换</button>
</div>
</template>
<script>
export default {
data() {
return {
count:1
list:[]
};
},
methods: {
handleChange() {
this.list.push({
id:this.count++,
name:'测试的dom列表元素'
})
},
},
};
</script>
<style scoped>
.demo-enter,
.demo-leave-to {
opacity: 0;
}
.demo-enter-active,
.demo-leave-active {
transition: opacity 1s;
}
</style>
4.2、transition-group原理
transition-group原理实际上就是给每一个列表循环的单独的元素外套一层transition标签,实际上就是单个元素的过渡动画。
v-for使用注意:for循环的时候key值尽量不要使用index索引,会导致性能降低,其次项目功能上也会造成一定的影响,如果能不用index作为key值,尽量不要使用index作为key值。
5、封装Vue动画
利用组件和slot的方式,将动画可以封装为一个组件,这样可以通过调用的方式复用相同的动画
5.1、封装动画(目前处于学习阶段:只是简单的封装)
<template>
<div class="transition">
<transition :name="name" mode="in-out">
<slot v-if="show"></slot>
</transition>
</div>
</template>
<script>
export default {
data() {
return {
};
},
props: ["name", "show"],
};
</script>
<style scoped>
</style>
5.2、使用封装的动画组件
<template>
<div class="about">
<demo :show="show" name="demo">
<div class="box">demo动画元素</div>
</demo>
<demo :show="show" name="txt">
<div class="txt">
第二个demo动画元素
</div>
</demo>
<demo :show="show" name="retxt">
<div class="retxt">
第三个demo动画元素
</div>
</demo>
<button @click="handler">点击执行动画</button>
</div>
</template>
<script>
import demo from "@/components/transition";
export default {
components: { demo },
data() {
return {
show: true,
};
},
methods: {
handler(){
this.show=!this.show;
}
},
};
</script>
<style scoped>
.retxt {
position: absolute;
top: 180px;
left: 650px;
width: 160px;
height: 30px;
background-color: green;
opacity: 0.5;
}
.retxt-enter,
.retxt-leave-to {
left: 300px;
}
.retxt-enter-active,
.retxt-leave-active {
transition: all 5s;
}
.txt {
position: absolute;
top: 300px;
left: 300px;
width: 160px;
height: 30px;
background-color: tomato;
opacity: 0.5;
}
.txt-enter,
.txt-leave-to {
left: 650px;
}
.txt-enter-active,
.txt-leave-active {
transition: all 5s;
}
.box {
font-size: 30px;
font-weight: bold;
}
.demo-enter,
.demo-leave-to {
opacity: 0;
}
.demo-enter-active,
.demo-leave-active {
transition: all 5s;
}
</style>