Vue3 学习笔记 —— transition、transition-group

目录

1. transition 动画组件

1.1 tansition 组件基础用法

1.2 自定义类名,并使用 animate.css

1.2.1 自定义类名

1.2.2 animate.css 动画库

1.3 transition 生命周期,使用 GSAP

1.3.1 transition 生命周期

1.3.2 使用 GSAP 实现动画效果(Vue 官网推荐)

1.4 appear

2. transition-group 动画列表

2.1 列表项过渡

2.2 平面过渡

2.2.1 初始化数组的小技巧

2.2.2 安装 lodash ts 声明文件

2.2.3 生成平面过渡的表格

2.3 状态过渡


1. transition 动画组件

1.1 tansition 组件基础用法

transition 组件,用于给包裹元素添加 进入/离开 过渡动画

transition 组件上可以接收 name 属性,用于指定六种动画类名前缀(此处以 fade 为栗子)

  • fade-enter-from
  • fade-enter-active
  • fade-enter-to
  • fade-leave-from
  • fade-leave-active
  • fade-leave-to

动画类名前面的 fade,就是给 transition 指定的 name,动画类名的后面是固定写法

<template>
<div>
  <button @click="flag = !flag">
    切换
  </button>
  <!-- 条件渲染 -->
  <transition name="fade">
    <div v-if="flag" class="my-box"></div>
  </transition>
  <!-- 条件展示 -->
  <transition name="fade">
    <div v-show="flag" class="my-box"></div>
  </transition>
  <!-- 动态组件 -->
  <transition name="fade">
    <component is="A"></component>
  </transition>
</div>
</template>

<script lang="ts" setup>
import { reactive, toRefs, defineComponent } from 'vue';

const flag = ref(true);
</script>

<style lang="scss" scoped>
/* 进入开始 */
.fade-enter-from {
  width: 0px;
  height: 0px;
  background: rgb(255, 153, 0);
  transform: rotate(360deg);
}
/* 进入中 */
.fade-enter-active {
  transition: all 1s linear;
}
/* 进入完成 */
.fade-enter-to {
  width: 200px;
  height: 200px;
  background: rgb(255, 0, 0);
}
/* 离开开始 */
.fade-leave-from {
  width: 200px;
  height: 200px;
}
/* 离开中 */
.fade-leave-active {
  transition: all 0.5s linear;
}
/* 离开完成 */
.fade-leave-to {
  width: 0px;
  height: 0px;
}
</style>

1.2 自定义类名,并使用 animate.css

1.2.1 自定义类名

transition 组件定义了以下 props,用于接收:

  • 自定义过渡类名
  • 自定义过渡时间(可以直接传入毫秒数,也可以分别定义进入或离开时的毫秒数)

举个栗子~~ 

  <!-- :duration="1000" -->
  <transition
    :enter-from-class="'classA'"
    :enter-active-class="'classB'"
    :enter-to-class="'classC'"
    :leave-from-class="'classD'"
    :leave-active-class="'classE'"
    :leave-to-class="'classF'"
    :duration="{ enter: 500, leave: 800 }"
  >
    <component is="A"></component>
  </transition>

1.2.2 animate.css 动画库

通过 transition 自定义 class,结合 animate.css 动画库,就能实现多种动画效果

Animate.css | A cross-browser library of CSS animations.Animate.css is a library of ready-to-use, cross-browser animations for you to use in your projects. Great for emphasis, home pages, sliders, and attention-guiding hints.https://animate.style/

// 安装 animate.css

npm install animate.css --save

yarn add animate.css

// 在 main.ts 中引入 animate.css

import 'animate.css'

举个栗子~~

<transition
  leave-active-class="animate__animated animate__bounceInLeft"
  enter-active-class="animate__animated animate__bounceInRight"
>
  <div v-if="flag" class="my-box"></div>
</transition>

注意:一定要添加类名前缀 animate__animated,否则动画效果无法生效

1.3 transition 生命周期,使用 GSAP

1.3.1 transition 生命周期

transition 的生命周期,相对于 props 多了两条:

  • 显示过渡打断
  • 离开过渡打断

生命周期具体包含以下几种:

  @before-enter="beforeEnter" --- 对应 enter-from
  @enter="enter" --- 对应 enter-active
  @after-enter="afterEnter" --- 对应 enter-to
  @enter-cancelled="enterCancelled" --- 显示过渡打断(多出来的)
  @before-leave="beforeLeave" --- 对应 leave-from
  @leave="leave" --- 对应 leave-active
  @after-leave="afterLeave" --- 对应 leave-to
  @leave-cancelled="leaveCancelled" --- 离开过渡打断(多出来的)

注意事项:

  • 每个生命周期函数接收一个 el 参数,标识执行过渡动画的 DOM 元素
  • enter / leave 函数除了 el 参数,还接收 done 参数,标识动画执行完成(举个栗子:enter 动画执行过程为 3s,加了 done 函数后,三秒之后才执行 after-enter,不加则 同步执行 两个函数)
  • 只用 JavaScript 过渡时,在 enter 和 leave 钩子中,必须使用 done 进行回调
  • enter-cancelled / leave-cancelled 函数指 当元素在执行完动画之前,就已经被按钮控制隐藏了,此时就会调用打断函数
  <transition
    :before-enter="enterFrom"
    :enter="enterActive"
    :after-enter="enterTo"
    :enter-cancelled="enterCancel"
    :before-leave="leaveFrom"
    :leave="leaveActive"
    :after-leave="leaveTo"
    :leave-cancelled="leaveCancel"
  >
    <component is="A"></component>
  </transition>


// before-enter
const enterFrom = (el: Element) => {
  console.log('进入之前');
};

/**
 * enter
 * @param el 执行过渡动画的 DOM 元素
 * @param done 标识动画执行完成
 */
const enterActive = (el: Element, done: Function) => {
  console.log('过渡曲线');
  setTimeout(() => {
    // 三秒后,此动画执行完毕,可以打印下面的 过渡完成 了
    done();
  }, 3000);
};

// after-enter
const enterTo = (el: Element) => {
  console.log('过渡完成');
};

// enter-cancelled
const enterCancel = (el: Element) => {
  console.log('过渡效果被打断');
  console.log('在 3s 内过渡效果还没完成,元素就隐藏了,此时就会执行被打断函数');
};

1.3.2 使用 GSAP 实现动画效果(Vue 官网推荐)

nullGSAP is an industry standard JavaScript animation library from GreenSock that lets you craft high-performance animations that work in every major browser.https://greensock.com/

// 使用 cdn 的方式引入

https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.3/gsap.min.js

// 使用 npm 进行安装

npm install gsap

注意事项:

  • gsap.set —— 动画初始状态
  • gsap.to —— 动画最终状态 
  • onComplete —— gsap 中,过渡完成的回调函数
  • done 函数 ts 类型报错 —— 将 Function 类型替换为 gsap.Callback 即可
  <transition
    :before-enter="enterFrom"
    :enter="enterActive"
    :leave="leaveActive"
  >
    <component is="A"></component>
  </transition>

import gsap from 'gsap';

// before-enter
const enterFrom = (el: Element) => {
  console.log('进入之前');
  gsap.set(el, {
    width: 0,
    height: 0,
  });
};

/**
 * enter
 * @param el 执行过渡动画的 DOM 元素
 * @param done 标识动画执行完成
 * @decription 关于 done 类型的报错,使用 gsap.Callback 替换 Function
 */
const enterActive = (el: Element, done: gsap.Callback) => {
  console.log('过渡曲线');
  gsap.to(el, {
    width: 200,
    height: 200,
    // 过渡完成的回调函数
    onComplete: done,
  });
};

/**
 * leave
 * @param el 执行过渡动画的 DOM 元素
 * @param done 标识动画执行完成
 * @decription 关于 done 类型的报错,使用 gsap.Callback 替换 Function
 */
const leaveActive = (el: Element, done: gsap.Callback) => {
  console.log('过渡曲线');
  gsap.to(el, {
    width: 0,
    height: 0,
    // 过渡完成的回调函数
    onComplete: done,
  });
};

1.4 appear

appear 属性 —— 设置 页面加载完成后,首次、立刻执行的动画

appear 有三个状态,可以接收自定义类名(可以结合 animate.css 使用)

<template>
  <transition
    appear
    appear-from-class="appear-from"
    appear-active-class="appear-active"
    appear-to-class="appear-to"
  >
    <component is="A"></component>
  </transition>
</template>

...

<style lang="scss" scoped>
.appear-from {
  width: 0px;
  height: 0px;
}

.appear-active {
  transition: all 0.5s linear;
}

.appear-to {
  width: 200px;
  height: 200px;
}
</style>

2. transition-group 动画列表

参考视频(强烈推荐,小满讲的非常清楚)

小满Vue3(第二十二章 transitionGroup)_哔哩哔哩_bilibili小满Vue3(第二十二章 transitionGroup)是Vue3 + vite + Ts + pinia + 实战 + 源码 +electron的第27集视频,该合集共计110集,视频收藏或关注UP主,及时了解更多相关视频内容。https://www.bilibili.com/video/BV1dS4y1y7vd?p=27&vd_source=8bc01635b95dbe8ecd349b2c23b03a10

2.1 列表项过渡

transition-group 组件的 props、生命周期 和 transition 组件一模一样

注意事项:

  • transition-group 接收 tag 属性,用于自动生成一个 包裹列表项的 DOM 元素
  • transition-group 内部的元素,一般是循环出来的列表项,一定要使用 key 标识唯一值
  • transition-group 的样式会在列表项中生效,而不是列表容器
<template>
  <button @click="addItem">
    新增列表项
  </button>
  <button @click="removeItem">
    删除列表项
  </button>

  <!-- 过渡列表 -->
  <div class="list-wrap">
    <transition-group
      tag="section"
      enter-active-class="animate__animated animate__bounceIn"
      leave-active-class="animate__animated animate__hinge"
    >
      <div v-for="item in list" :key="item" class="list-item">
        {{ item }}
      </div>
    </transition-group>
  </div>
</template>

<script lang="ts" setup>
import { reactive } from 'vue';
import 'animate.css';

const list = reactive<number[]>([1, 2, 3, 4, 5, 6]);

const addItem = () => {
  list.push(list.length + 1);
};

const removeItem = () => {
  list.pop();
};
</script>

<style lang="scss" scoped>
.list {
  &-wrap {
    display: flex;
    flex-wrap: wrap;
    word-break: break-all;
    border: 1px solid #D7D7D7;
  }
  &-item {
    margin: 10px;
    font-size: 20px;
  }
}
</style>

2.2 平面过渡

2.2.1 初始化数组的小技巧

如果使用 new Array(81) 直接生成数组,那么不会初始化数组的每一项

如果使用 apply 生成数组,则初始化时,会自动填充数组每一项为 undefined

2.2.2 安装 lodash ts 声明文件

Lodash 简介 | Lodash 中文文档 | Lodash 中文网Lodash 是一个一致性、模块化、高性能的 JavaScript 实用工具库。https://www.lodashjs.com/

执行下方命令安装 lodash

npm i --save lodash

安装完毕后,可能出现报错,因为没有安装 ts 类型声明文件,执行下方命令安装

npm install @types/lodash -D

lodash.shuffle —— 将数组内的元素,随机打乱顺序

2.2.3 生成平面过渡的表格

场景描述:生成9行9列的表格,点击按钮后,实现单元格平面移动的效果

<template>
  <div>
    <button @click="shuffleArray">
      随机打乱数组内元素的顺序
    </button>

    <transition-group tag="ul" class="list-wraps">
      <!-- 一定要绑定 key,否则会不生效 -->
      <li v-for="item in testList" :key="item.id" class="list-cell">
        {{ item.number }}
      </li>
    </transition-group>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
// 别忘记装 ts 声明文件:npm install @types/lodash -D
import _ from 'lodash';

/*
 * [
 *   { id: 1, number: 1 },
 *   { id: 8, number: 8 },
 *   { id: 18, number: 1 },
 *   { id: 27, number: 1 },
 * ]
 */

const testList = ref(
  Array.apply(null, { length: 81 } as number[]).map((_, index) => ({
    id: index,
    // 每 9 个为一组
    number: (index % 9) + 1,
  })),
);

/**
 * 将数组内的元素,随机打乱顺序
 */
const shuffleArray = () => {
  testList.value = _.shuffle(testList.value);
};
</script>

<style scoped lang="less">
.list-wraps {
  display: flex;
  flex-wrap: wrap;
  // 每 9 个一排
  width: calc(25px * 10 + 9px);
  .list-cell {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 25px;
    height: 25px;
    border: 1px solid #dcdcdc;
    list-style-type: none;
  }
}
</style>

2.3 状态过渡

举个栗子:数字从 9999 变成 1 时,添加滚动状态过渡的效果

再举个栗子:背景色从 红色 变成 蓝色 时,添加背景色过渡的效果

<template>
  <div>
    <!-- step 每次数字变动大小为 20 -->
    <input v-model="state.inputNumber" type="number" step="20" />
    <!-- 展示过渡效果的值 -->
    <div>{{ state.showTransitionNumber.toFixed(0) }}</div>
  </div>
</template>

<script setup lang='ts'>
import { reactive, watch } from 'vue';
import gsap from 'gsap';

const state = reactive({
  // 使用 input 改变的值
  inputNumber: 0,
  // 展示过渡效果的值
  showTransitionNumber: 0,
});

/**
 * 当 input 数字改变时,调整 展示过渡效果的值
 */
watch(() => state.inputNumber, (newVal) => {
  gsap.to(state, {
    // 过渡时间
    duration: 1,
    // 将 展示过渡效果的值 从原来的值,替换为 使用 input 改变的值
    showTransitionNumber: newVal,
  });
});

</script>

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lyrelion

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值