# transition-group 元件 >[竹白記事本](https://chupainotebook.bloggi.co/) [Vue Transition|目錄](https://hackmd.io/@chupai/HkQQA8c4U) ###### tags: `Vue Transition` `竹白的 Vue.js 學習筆記` ## 大量元素的轉場 目前為止,都是針對單個節點,或是同一時間渲染多個節點中的一個。如果要針對由 `v-for` 產生的大量元素(例如:列表),就要改為使用 transition-group 元件。 transition-group 元件有以下幾個特點: - 不同於 `<transition>`,它會以一個真實元素呈現:預設為一個 `<span>`。可以通過 `tag` 特性更換為其他元素。 - 轉場模式(`in-out` 與 `out-in`)不可用,因為我們不再相互切換特有的元素。 - 內部元素 **總是需要** 提供唯一的 `key` 屬性值。 - CSS 轉場的類將會應用在內部的元素中,而不是這個組/容器本身。 ### 1. 進入/離開的轉場 首先我們看一段程式碼: ```htmlmixed <button v-on:click="add">Add</button> <button v-on:click="remove">Remove</button> <ul> <li v-for="item in items" :key="item" class="list-item"> {{ item }} </ul> ``` 按下 Add 會隨機插入數字,按下 Remove 會隨機移除數字。 <iframe height="265" style="width: 100%;" scrolling="no" title="Vue 大量元素的轉場 " src="https://codepen.io/CHUPAIWANG/embed/povELjR?height=265&theme-id=dark&default-tab=result" frameborder="no" allowtransparency="true" allowfullscreen="true"> See the Pen <a href='https://codepen.io/CHUPAIWANG/pen/povELjR'>Vue 大量元素的轉場 </a> by CHUPAIWANG (<a href='https://codepen.io/CHUPAIWANG'>@CHUPAIWANG</a>) on <a href='https://codepen.io'>CodePen</a>. </iframe> 接下來我們改用 transition-group 元件,增加轉場效果。 transition-group 元件預設會有一個 `<span>` 的根元素,它會包住由 `v-for` 產生的多個元素當成其子元素。 我們透過 `tag` 特性,將其改成 `<ul>`: ```htmlmixed <transition-group name="list" tag="ul"> <li v-for="item in items" v-bind:key="item" class="list-item"> {{ item }} </li> </transition-group> ``` 並加上 CSS: ```css .list-enter, .list-leave-to { opacity: 0; transform: translateY(100%); } .list-leave, .list-enter-to { opacity: 1; } .list-enter-active, .list-leave-active { transition: all 1s; } ``` <iframe height="265" style="width: 100%;" scrolling="no" title="Vue 大量元素的轉場 - transition-group" src="https://codepen.io/CHUPAIWANG/embed/RwPZgwM?height=265&theme-id=dark&default-tab=result" frameborder="no" allowtransparency="true" allowfullscreen="true"> See the Pen <a href='https://codepen.io/CHUPAIWANG/pen/RwPZgwM'>Vue 大量元素的轉場 - transition-group</a> by CHUPAIWANG (<a href='https://codepen.io/CHUPAIWANG'>@CHUPAIWANG</a>) on <a href='https://codepen.io'>CodePen</a>. </iframe> 不過這個範例有一個明顯問題,當新增和移除元素的時候,周圍的元素會瞬間移動到他們的新佈局的位置,這會顯得不自然,我們將會在之後解決這個問題。 ### 2. 排序轉場 transition-group 元件還有一個特殊之處。不僅可以進入和離開動畫,還可以改變定位。 `v-move` 特性,它會在元素的改變定位的過程中應用。像之前的列別名稱一樣,可以通過 `name` 屬性來自定義前綴,也可以通過 `move-class` 屬性手動設置。 `v-move` 對於設置轉場的切換時機和轉場曲線非常有用。 ```htmlmixed <button v-on:click="items.reverse()">Reverses</button> <transition-group name="flip-list" tag="ul"> <li v-for="item in items" :key="item" class="list-item">{{ item }} </li> </transition-group> ``` ```css .flip-list-move { transition: transform 1s; } ``` ```javascript const vm = new Vue({ el: '#app', data: { items: [1, 2, 3, 4, 5, 6, 7, 8, 9], }, }); ``` <iframe height="400" style="width: 100%;" scrolling="no" title="Vue 大量元素的轉場 - v-move" src="https://codepen.io/CHUPAIWANG/embed/bGNwzwz?height=265&theme-id=default&default-tab=result" frameborder="no" allowtransparency="true" allowfullscreen="true"> See the Pen <a href='https://codepen.io/CHUPAIWANG/pen/bGNwzwz'>Vue 大量元素的轉場 - v-move</a> by CHUPAIWANG (<a href='https://codepen.io/CHUPAIWANG'>@CHUPAIWANG</a>) on <a href='https://codepen.io'>CodePen</a>. </iframe> Vue 使用了一個叫 [FLIP](https://aerotwist.com/blog/flip-your-animations/) 簡單的動畫隊列。使用 `transforms` 將元素從之前的位置平滑轉場新的位置。 讓我們修正上節不自然的的程式碼: ```css .list-move-active { position: absolute; } .list-move { transition: 1s; } ``` <iframe height="265" style="width: 100%;" scrolling="no" title="Vue 大量元素的轉場 - 進入/離開的轉場 v-move" src="https://codepen.io/CHUPAIWANG/embed/KKwgJNO?height=265&theme-id=default&default-tab=result" frameborder="no" allowtransparency="true" allowfullscreen="true"> See the Pen <a href='https://codepen.io/CHUPAIWANG/pen/KKwgJNO'>Vue 大量元素的轉場 - 進入/離開的轉場 v-move</a> by CHUPAIWANG (<a href='https://codepen.io/CHUPAIWANG'>@CHUPAIWANG</a>) on <a href='https://codepen.io'>CodePen</a>. </iframe> :::danger 另外要注意,FLIP 轉場的元素不能設置為 `display: inline`。作為替代方案,可以設置為 `display: inline-block`、`display: flex-block` 或者放置於 FlexBox 父容器中 ::: <iframe height="500" style="width: 100%;" scrolling="no" title="Vue 大量元素的轉場 - 打亂" src="https://codepen.io/CHUPAIWANG/embed/VwLzMxp?height=265&theme-id=dark&default-tab=result" frameborder="no" allowtransparency="true" allowfullscreen="true"> See the Pen <a href='https://codepen.io/CHUPAIWANG/pen/VwLzMxp'>Vue 大量元素的轉場 - 打亂</a> by CHUPAIWANG (<a href='https://codepen.io/CHUPAIWANG'>@CHUPAIWANG</a>) on <a href='https://codepen.io'>CodePen</a>. </iframe>