目录

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>

Logo

前往低代码交流专区

更多推荐