目錄
-
- 最終效果
- 一、無過渡動畫的手風琴
- 二、有過渡動畫的手風琴
-
- 1. 不能再用v-if或v-show
- 2. 用:class動态綁定樣式
- 3. 子元素也要設定transition
最終效果
UI同學讓做一個帶過渡動畫的手風琴折疊效果,點選一個元素展開,其他已展開元素自動收縮,每次最多隻有一個元素展開,這是最終效果:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmL4YjN4AzNwEDM0ETNwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.gif)
接下來講我用css實作的思路
一、無過渡動畫的手風琴
首先,uniapp做無過渡動畫的最容易做了,因為Vue裡隻要用
v-if
或
v-show
來控制,判斷index是否是目前的子元件就好了。因為我用了元件,我想父元件的事件
openDetail
觸發能更新子元件的資料,是以我用
:ref
來更新子元件的boolean變量
isOpen
來觸發
v-show="isOpen"
,記錄
lastIndex
來關閉上個展開的子元件,確定每次點選最多隻有一個展開。
父元件
<view>
<collapse-item v-for="(item, index) in list" :key="index"
@tap="openDetail(index)" :ref="'collapse'+index"
</collapse-item>
</view>
...
<script>
export default {
data() {
return {
lastIndex: -1;
}
},
methods: {
// 手風琴式收縮展示offer清單
if (index != this.lastIndex && this.lastIndex >= 0) {
this.$refs['collapse'+this.lastIndex][0].isOpen = false;
this.$refs['collapse'+index][0].isOpen = !this.$refs['collapse'+index][0].isOpen;
} else {
this.$refs['collapse'+index][0].isOpen = !this.$refs['collapse'+index][0].isOpen;
}
this.lastIndex = index;
}
}
</script>
子元件collapse-item
<view v-show="isOpen">
<view>專業</view>
<view>均分</view>
<view>入學</view>
</view>
...
export default {
data() {
return {
isOpen: false,
}
},
}
二、有過渡動畫的手風琴
現在來做過渡動畫,我在做的時候,發現有以下幾點需要注意:
1. 不能再用v-if或v-show
過渡動畫的css實作大家肯定能想到是
transition
,而
transition
的動畫是基于兩個狀态的來回變化的,不管是
v-if
的增删DOM節點還是v-show的
display: none
都是隻有一個狀态,無法滿足前後兩個狀态,
transition
會失效。
2. 用:class動态綁定樣式
可以用
:class
的對象文法
:class="isOpen ? 'content-open' : 'content-close'"
來動态綁定展開和收起兩種狀态的樣式。
展開狀态設定高度
height
值,而收起狀态設
height
為0,兩個狀态都設定
transition
,就能實作過渡動畫。
我們來更新一下子元件collapse-item的代碼:
<view :class="isOpen ? 'content-open' : 'content-close'">
<view :style="{height: isOpen ? '40rpx' : '0'}">專業</view>
<view :style="{height: isOpen ? '40rpx' : '0'}">均分</view>
<view :style="{height: isOpen ? '40rpx' : '0'}">入學</view>
</view>
...
export default {
data() {
return {
isOpen: false,
}
},
}
...
<style>
.content-open {
height: 180 rpx;
transition: all 0.4s cubic-bezier(0.25, 1.0, 0.25, 1.0);
}
.content-close {
height: 0;
transition: all 0.4s cubic-bezier(0.25, 1.0, 0.25, 1.0);
}
</style>
3. 子元素也要設定transition
寫完上面的代碼以後,我發現了一個問題,文字出現的比背景顔色快,在背景顔色還沒有過渡動畫展開完時,文字就已經全出現了,而且文字并沒有像我預想一樣的也有展開動畫效果。
問題雖然不大,但是視覺上給人的體驗非常不好,是以我一定要解決。
正當我無比困惑時,我突然想到,是不是
transition
屬性無法繼承?
我就查了一下W3C文檔:https://drafts.csswg.org/css-transitions/
果然
transition
是
inherited:no
,無法繼承的。
是以我們子元素也都要設定
transition
,才能達到背景顔色和文字同時有過渡動畫的展開和收起的效果。
再更新一下子元件的代碼:
<view :class="isOpen ? 'content-open' : 'content-close'">
<view :class="isOpen ? 'item-open' : 'item-close'">專業</view>
<view :class="isOpen ? 'item-open' : 'item-close'">均分</view>
<view :class="isOpen ? 'item-open' : 'item-close'">入學</view>
</view>
...
export default {
data() {
return {
isOpen: false,
}
},
}
...
<style>
.content-open {
height: 180 rpx;
overflow: hidden;
transition: all 0.4s cubic-bezier(0.25, 1.0, 0.25, 1.0);
}
.content-close {
height: 0;
transition: all 0.4s cubic-bezier(0.25, 1.0, 0.25, 1.0);
}
.item-open {
height: 40rpx;
transition: all 0.4s cubic-bezier(0.25, 1.0, 0.25, 1.0);
}
.item-close {
opacity: 0;
height: 0;
}
</style>
content-open
裡設定
overflow: hidden
,展開時文字就不會浮在下一個元素上。
至于我為什麼子元素的
item-close
不設定
transition
呢,因為三行文字先會縮成一行重疊的字再消失,太醜了,大家試試就知道了,是以幹脆文字在close時直接消失好了~
我們的帶過渡動畫的手風琴折疊效果就做好啦,效果和文章開頭的圖一樣~
覺得有用的請點個贊,謝謝大家的觀看~轉載請帶本文連結