vue3学习记录-TransitionGroup
- 1.概念
- 2.基本使用
-
- [2.1 进入 / 离开动画](#2.1 进入 / 离开动画)
- [2.2 移动动画](#2.2 移动动画)
- [2.3 和第三方库搭配](#2.3 和第三方库搭配)
- [2.4 appear 高级的自动加载动画](#2.4 appear 高级的自动加载动画)
1.概念
TransitionGroup 是一个内置组件,用于对 v-for 列表中的元素或组件的插入、移除和顺序改变添加动画效果。
和 Transition的区别:
默认情况下,它不会渲染一个容器元素。但你可以通过传入 tag prop 来指定一个元素作为容器元素来渲染。
过渡模式在这里不可用,因为我们不再是在互斥的元素之间进行切换。
列表中的每个元素都必须有一个独一无二的 key attribute。
CSS 过渡 class 会被应用在列表内的元素上,而不是容器元素上。
TransitionGroup 比Transition多了两个prop,一个是tag,如果如果未定义,则渲染为片段 (fragment),如果定义了,例如tag="div",v-for的上一层,TransitionGroup 会被渲染成div。另一个prop是moveClass,用于自定义过渡期间被应用的 CSS class。,在模板中使用 kebab-case,例如 move-class="xxx"。
2.基本使用
2.1 进入 / 离开动画
javascript
<script setup>
import { ref } from 'vue';
const list = ref([1, 2, 3, 4, 5])
const add = () => {
list.value.push(Math.floor(Math.random() * 10) + 1);
}
const remove = () => {
list.value.pop();
}
</script>
<template>
<el-button @click="add">add</el-button>
<el-button @click="remove">remove</el-button>
<transition-group tag="div" class="list">
<div v-for="item in list" class="item" :key="item">{{ item }}</div>
</transition-group>
</template>
<style scoped>
.list {
display: flex;
width: 30px;
flex-wrap: wrap;
.item {
width: 20px;
margin: 5px;
height: 20px;
text-align: center;
}
}
.list-enter-active,
.list-leave-active {
transition: all 0.5s ease;
}
.list-enter-from,
.list-leave-to {
opacity: 0;
transform: translateX(30px);
}
.v-enter-active,
.v-leave-active {
transition: all 0.5s ease;
}
.v-enter-from,
.v-leave-to {
opacity: 0;
transform: translateX(30px);
}
</style>
默认情况下, 不会渲染一个容器 DOM 元素,但是可以通过 tag prop 启用。
注意,每个 transition-group 的子节点必须有独立的 key,动画才能正常工作。
支持通过 CSS transform 控制移动效果。当一个子节点在屏幕上的位置在更新之后发生变化时,它会被添加一个使其位移的 CSS class (基于 name attribute 推导,或使用 move-class prop 显式配置)。如果使其位移的 class 被添加时 CSS 的 transform 属性是"可过渡的",那么该元素会基于 FLIP 技巧平滑地到达动画终点。
如果两个都没定义的话,就是默认的例子中的.v-enter-active,.v-leave-active,.v-enter-from,.v-leave-to CSSclasss。
2.2 移动动画
上面的会有个问题,发现在随机移动的时候没有动画。
我们可以通过添加一些额外的 CSS 规则来解决这个问题:
javascript
.list-move, /* 对移动中的元素应用的过渡 */
.list-enter-active,
.list-leave-active {
transition: all 0.5s ease;
}
.list-enter-from,
.list-leave-to {
opacity: 0;
transform: translateX(30px);
}
/* 确保将离开的元素从布局流中删除
以便能够正确地计算移动的动画。 */
.list-leave-active {
position: absolute;
}
效果:
2.3 和第三方库搭配
javascript
<script setup>
import gsap from 'gsap';
import { ref,reactive,watch } from 'vue';
const num = reactive({
current: 1,
show: 1
})
watch(() => num.current, (val) => {
gsap.to(
num,
{
duration: 1,
show:val
}
)
})
</script>
<template>
<el-input-number
v-model="num.current"
:min="1"
controls-position="right"
:step="20"
/>
<p>{{ num.show.toFixed(0) }}</p>
</template>
效果:
transition的appear和js钩子也都适用transition-group的
2.4 appear 高级的自动加载动画
一直在想用appear属性能实现高级的自动加载动画吗
javascript
<script setup>
import { ref, onMounted } from 'vue';
import gsap from 'gsap';
// 模拟数据列表
const items = ref([
{ id: 1, title: 'Item 1' },
{ id: 2, title: 'Item 2' },
{ id: 3, title: 'Item 3' },
{ id: 4, title: 'Item 4' },
{ id: 5, title: 'Item 5' },
]);
// 控制是否显示列表
const showList = ref(false);
// GSAP 动画函数
const onBeforeEnter = (el) => {
gsap.set(el, {
opacity: 0,
y: 50,
scale: 0.8,
});
};
const onEnter = (el, done) => {
gsap.to(el, {
opacity: 1,
y: 0,
scale: 1,
duration: 0.6,
ease: 'back.out(1.7)',
onComplete: done,
});
};
const onAfterEnter = (el) => {
gsap.to(el, {
scale: 1.05,
duration: 0.2,
yoyo: true,
repeat: 1,
});
};
// 组件挂载后显示列表
onMounted(() => {
setTimeout(() => {
showList.value = true;
}, 500); // 延迟 500ms 显示列表
});
</script>
<template>
<div class="container">
<transition-group appear @before-enter="onBeforeEnter" @enter="onEnter" @after-enter="onAfterEnter">
<div v-if="showList" v-for="item in items" :key="item.id" class="item">
{{ item.title }}
</div>
</transition-group>
</div>
</template>
<style scoped>
.container {
max-width: 600px;
margin: 0 auto;
padding: 20px;
}
.item {
background-color: #f0f0f0;
border-radius: 8px;
padding: 15px;
margin-bottom: 10px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
</style>
效果 :
其实好像用不用appear都能实现高级的自动加载动画