[筆記] 解決 height: auto 沒有動畫之用 Vue 3 組合式函數完美實現摺疊效果

章節連結

筆記一下常用的摺疊效果,要如何避免因為 height: auto 而導致動畫效果無法觸發的問題。

vue.js logo vue


內容

1. htmlElement.offsetHeight

由於 JavaScript 並不會每一行 JS 執行時,就屢屢重繪畫面。因此若你在短短數行就執行「高度設為 0,然後高度變為 200px」之類的,瀏覽器會僅執行 height 變為 200px,但高度變化效果就消失了。

因此 htmlElement.offsetHeight 的執行,就是告知瀏覽器「請重排」當前畫面。這樣一來過渡過程就會出現了

2. 執行完畢後的 cleanup 函式

當展開效果執行完後,要讓 height 設為 auto,並將相關的動畫效果改為空值;反之當關閉時,display 要設為 none,height 要設為空值

3. transitionend 和 setTimeout:確保 cleanup 函式一定會執行

由於 transitionend 不一定會執行。當其不執行時,設定一個 setTimeout 來確保 cleanup 函式一定會執行。

以下是導致 transitionend 不執行的原因:

A. 如果在動畫進行中,父元素突然被 v-if 移除,或者設置了 display: none,動畫會立即終止,transitionend 永遠不會被拋出
B. 如果你設定的高度與目前高度完全一樣(例如原本就是 0px,又觸發了一次變為 0px 的動畫),瀏覽器可能不會啟動 transition,自然也不會有結尾事件。
C. 瀏覽器標籤頁切換:當使用者切換到別的視窗時,瀏覽器為了節省效能會暫停動畫計時,有時會導致事件監聽器的邏輯進入異常狀態。

4. onBeforeUnmount 清除 timer

確保元素消除時,一定不會留有沒用到的計時器


程式碼

按讚加入粉絲團

延伸閱讀