transition过渡效果
所谓的过渡,在dom元素 插入,更新或者移除dom时,给dom元素加上过渡动画,使之看起来没那么生硬,transition的作用其实就是给过渡的元素在显示/隐藏
,插入/移除
时添加一些class
过渡条件
- 条件渲染(v-if)
- 条件展示(v-show)
- 动态组件
- 根元素
当元素插入或删除时包含在transition
组件中的元素Vue将会做一下处理
- 自动嗅探目标元素是否应用了 CSS 过渡或动画,如果是,在恰当的时机添加/删除 CSS 类名
- 如果过渡组件提供了 JavaScript 钩子函数,这些钩子函数将在恰当的时机被调用
- 如果没有找到 JavaScript 钩子并且也没有检测到 CSS 过渡/动画,DOM 操作 (插入/删除) 在下一帧中立即执行
过渡的类名
在进入/离开的过渡中,会有6个class切换
- v-enter – 定义进入过渡的开始状态
- v-enter-active – 定义进入过渡生效时的状态,我们可以在这里定义一些我们想要的动画
- v-enter-to – 定义进入过渡的结束状态
- v-leave – 定义离开过渡的开始状态
- v-leave-active – 定义离开过渡生效时的状态
- v-leave-to – 定义离开过渡的结束状态
在这六个class中,前三个是进入的时候的class, 后三个是离开时候的class,如下小例子:
<div id="box">
<button @:click="show = !show">
Toggle
</button>
<transition name="fade">
<p v-if="show">hello</p>
</transition>
</div>
<script>
new Vue({
el: '#box',
data: {
show: true
}
})
</script>
.fade-enter-active,
.fade-leave-active {
transition: opacity 1s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
在过渡的时候,如果我们没有定义name
属性,那么vue会以 v-
来作为这些类名的默认前缀。如果我们使用了name属性,如上例子中,vue会将name属性值会作为类名过渡的前缀,如 v-enter
会替换为 fade-enter
。这样我们可以给我们不同的过渡添加不同的过渡效果了
初始元素的动画
元素加载完成时就执行动画,我们只需要在transition上设置 appear
属性就好了
<div id="box">
<button @click="isShow=!isShow">click<on>
<transition name="fade" appear>
<div v-if="isShow">
111111111111111111111
</div>
</transition>
</div>
<script>
el: '#box',
data: {
isShow: true
}
</script>
多个元素的过渡
在多个元素的过渡中,我们要给每一项要切换的元素设置一个唯一的key值,这是因为vue的diff
算法,在元素切换的时候,匹配两个元素之间,只是内容不一样,那么之会将元素内容替换,而我们设置key值之后,就表示每一项都是唯一的,切换的时候也会很顺利了
过渡模式
在多个元素切换时,是否会有一个小bug,离开过渡和进来的过渡一起执行了,看起来不是那么理想,我们要用一个属性就可以解决了。那还是过渡模式mode
,可以有两个取值
in-out
– 新元素先进入过渡,完成之后当前元素过度离开out-in
– 当前元素先进入过渡,完成之后新元素咋过渡进入
<div id="box">
<button @click="isShow=!isShow">click</button>
<transition name="a" mode="out-in">
<div v-if="isShow" key="div1">
111111111111111111111
</div>
<div v-else key="div2">
2222222222222222222222222
</div>
</transition>
</div>
<script>
new Vue({
el:"#box",
data:{
isShow:true
}
})
</script>
多个组件的过渡
多个组件的过渡我们不需要绑key
了,我们只需要使用动态组件
<div id="box">
<keep-alive>
<transition name="b" mode="out-in">
<component :is="type"></component>
</transition>
</keep-alive>
<ul>
<li @click="type='home'">首页</li>
<li @click="type='list'">列表</li>
<li @click="type='shopcar'">购物车</li>
</ul>
</div>
<script>
Vue.component("home",{
template:`<div>home-<input type="text"/></div>`
})
Vue.component("list",{
template:`<div>list</div>`
})
Vue.component("shopcar",{
template:`<div>shopcar</div>`
})
new Vue({
el: '#box',
data: {
type: 'home'
}
})
</script>
多个列表的过渡
<transition-group>
,<transition-group
的tag
属性代表最后显示的dom元素
<div id="box">
<input type="text" v-model="mytext">
<button @click="handleClick()">add</button>
<transition-group tag="ul" name="b">
<li v-for="(item,index) in items" :key="item">
{{item}} -{{index}}
<button @click="handleDelClick(index)">del</button>
</li>
</transition-group>
</div>
<script>
new Vue({
el: '#box',
data: {
mytext: '',
items: ['111','222','333']
},
methods: {
handleClick() {
console.log("输入框value", this.mytext)
this.items.push(this.mytext)
},
handleDelClick(index) {
console.log("del", index)
this.items.splice(index, 1);
}
}
})
</script>
可复用的过渡
其实就是把过渡封装成组件,这样就可以实现过渡的复用了
<div id="box">
<button @click="isShow = !isShow">click</button>
<sidebar v-show="isShow">
<ul>
<li>1111</li>
<li>222</li>
<li>333</li>
</ul>
</sidebar>
</div>
<script>
Vue.component('sidebar', {
template: `<transition name="b">
<div style="background:red;width:200px;height:500px">
<slot></slot>
</div>
</transition>
`
})
new Vue({
el: '#box',
data: {
isShow: true
}
})
</script>