transition-group
transition只能过渡单个节点,或多个但每次只渲染一个。不能同时渲染多个节点。
假设需要用v-for渲染一整个列表,这种场景就不能使用transition,需要使用transition-group。
transition-group组件的特点:
- 默认不渲染一个包裹元素,但可以通过tag指定渲染一个包裹元素
- 过渡模式不可用,因为不再相互切换特有的元素
- 内部元素总是需要提供唯一的key值
- CSS过渡的类将会应用到内部的元素重,而非这个组/容器本身
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| <template> <div class="content"> <button @click="list.push(list.length+1)">ADD</button> <button @click="list.pop">POP</button> <div class="wraps"> <!-- 为tag属性赋值,渲染时会为内容加上对应的标签包裹,不写就没有 --> <!-- 自定义类名属性、生命周期都和transition一样 --> <transition-group enter-active-class="animate__animated animate__bounceIn" leave-active-class="animate__animated animate__hinge"> <div class="item" v-for="(item, index) in list" :key="index">{{ item }}</div> </transition-group> </div> </div> </template>
<script setup lang="ts"> import { reactive } from "vue" import "animate.css"
const list = reactive<number[]>([ 1, 2, 3, 4, 5, 6 ]) </script>
<style lang="scss"> .wraps { display: flex; flex-wrap: wrap; word-break: break-all; border: 1px solid #ccc; .item { margin: 10px; font-size: 30px; } } </style>
|
如果给transition-grop加上tag值(例如<transition-group tag="section">省略</transition-group>
):
列表的移动过渡
除了进入和离开外,transition-group还可以使用v-move为定位的改变添加动画。
和transition的类名一样,可以使用name定义前缀,或使用move-class自定义使用的类名。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| <template> <div> <button @click="random">random</button> <transition-group move-class="move" class="warps" tag="div"> <div class="item" v-for="item in list" :key="item.id">{{ item.number }}</div> </transition-group> </div> </template>
<script setup lang="ts"> import { ref } from "vue" import _ from "lodash"
// 使用new Array(81)会生成81项都为empty的数组 // 这种方式就会生成81项都是undefined的数组 const list = ref(Array.apply(null,{length:81} as number[]).map((_,index)=>{ return { id:index, number:(index%9)+1 } }))
const random = ()=> { list.value = _.shuffle(list.value) } </script>
<style lang="scss"> .warps { display: flex; flex-wrap: wrap; width: calc(27px * 9); .item { width: 25px; height: 25px; border: 1px solid #ccc; display: flex; justify-content: center; align-items: center; } } .move { transition: all 0.5s ease; } </style>
|
状态过渡
也可以给数字、SVG、背景颜色等添加过渡动画。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <template> <div> <input v-model="num.current" type="number" step="20"> <div> {{ num.tweenedNumber.toFixed(0) }} </div> </div> </template>
<script setup lang="ts"> import { reactive, watch } from "vue" import gsap from "gsap"
const num = reactive({ current:0, tweenedNumber:0 })
watch(()=> num.current, (newVal)=> { gsap.to(num,{ duration:1, tweenedNumber:newVal }) }) </script>
|