vue3学习记录-TransitionGroup

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都能实现高级的自动加载动画

相关推荐
雯0609~21 分钟前
网页F12:缓存的使用(设值、取值、删除)
前端·缓存
℘团子এ24 分钟前
vue3中如何上传文件到腾讯云的桶(cosbrowser)
前端·javascript·腾讯云
学习前端的小z30 分钟前
【前端】深入理解 JavaScript 逻辑运算符的优先级与短路求值机制
开发语言·前端·javascript
星星会笑滴33 分钟前
vue+node+Express+xlsx+emements-plus实现导入excel,并且将数据保存到数据库
vue.js·excel·express
CV学术叫叫兽37 分钟前
一站式学习:害虫识别与分类图像分割
学习·分类·数据挖掘
我们的五年1 小时前
【Linux课程学习】:进程程序替换,execl,execv,execlp,execvp,execve,execle,execvpe函数
linux·c++·学习
彭世瑜1 小时前
ts: TypeScript跳过检查/忽略类型检查
前端·javascript·typescript
FØund4041 小时前
antd form.setFieldsValue问题总结
前端·react.js·typescript·html
Backstroke fish1 小时前
Token刷新机制
前端·javascript·vue.js·typescript·vue
小五Five1 小时前
TypeScript项目中Axios的封装
开发语言·前端·javascript