Vue3| 使用transition组件改变DOM属性的方式(总结)

想要制作基于状态变化的过渡,使用vue内置组件、Class、动画库来快速实现;

  1. <Transition> 🔗 会在单个元素或组件进入和离开 DOM 时应用动画;
  2. <TransitionGroup> 🔗 会在一个 v-for 列表中的元素或组件被插入,移动,或移除时应用动画;
    下面使用Vue3的代码对DOM的widthheight属性进行过渡的不同实现方式

1、<transition> 标签

使用 name 属性 来定义class 来实现DOM的属性的过渡

vue3 复制代码
<template>
   <div>
      <button @click="flag = !flag">switch</button>
      <!-- 用法1  name属性定义class-->
      <transition name="fade">
        <div v-if="flag" class="box">name属性定义class</div>
      </transition>
    </div>
 </template>
      
<script setup lang='ts'>
    import{ref} from 'vue'

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


<style scoped lang="scss">
    .box{
        width: 200px;
        height: 200px;
        background-color: red;
    }
    .fade-enter-from { // 进入 从XX 开始
    width: 0;
    height: 0;
}
    .fade-enter-active {
        // 过程
        transition: all 1.5s ease;
    }
    .fade-enter-to { // 进入 到 XX 结束
        width: 200px;
        height: 200px;
        transform: scale(1.2); // 放大1.2倍
    }

    .fade-leave-from { // 离开 从XX 开始
        width: 200px;
        height: 200px;
    }
    .fade-leave-active {
        // 过程
        transition: all 1.5s ease;
    }
    .fade-leave-to { // 离开 到 XX 结束
        width: 0;
        height: 0;
    }
</style>

页面效果:

可以通过name属性,绑定指定name的class, 灵活定义过渡的进入离开时的效果;

上面方式缺点是class.xxx-enter-from -enter-from部分是固定的, 如果想要定义整个class名,可以使用<Transition> 另外属性;

进入:enter-from-classenter-active-classenter-to-class

离开:leave-from-classleave-active-classleave-to-class

vue3 复制代码
<template>
   <transition 
   enter-from-class="dada-enter-from"
   enter-active-class="dada-enter-active"
   enter-to-class="dada-enter-to"
   leave-from-class="dada-leave-from"
   leave-active-class="dada-leave-active"
   leave-to-class="dada-leave-to">
       <div v-if="flag" class="box">自定义类名</div>
   </transition>
</template>
...
<style scoped lang="scss">
dada-enter-from {
   width: 0;
   height: 0;
}
.dada-enter-active {
   // 过程
   transition: all 1.5s ease;
}
.dada-enter-to { // 进入 到 XX 结束
   width: 200px;
   height: 200px;
   transform: scale(1.2); // 放大1.2倍
}

.dada-leave-from {
   width: 200px;
   height: 200px;
}
.dada-leave-active {
   // 过程
   transition: all 1.5s ease;
}
.dada-leave-to { // 离开 到 XX 结束
   width: 0;
   height: 0;
}
</style>

页面效果:同上

<transition> + 动画库 animate.css

安装: npm install animate.css --saveyarn add animate.css

vue3 复制代码
<transition 
:duration="1000"
enter-active-class="animate__animated animate__flipInX"
leave-active-class="animate__animated animate__fadeOutDown">
        <div v-if="flag" class="box font-12">结合第三方类库 animate.css</div> 
</transition>
      
<script setup lang='ts'>
import 'animate.css'
</script>

属性duration:number|{enter:number, leave:number} 是指动画时长;如果进入离开定义相同时长,值可定义number类型,如果进入离开定义不同时长,值可定义object类型;

注意,使用class时不要漏加特定classanimate__animated

页面效果:

使用第三方CSS动画库,过渡效果丰富,减少自己写CSS代码,直接添加对应效果的class即可;

丰富有趣的交互效果,往往只有class是不够的,还需要通过JS代码控制动画来实现;

想要通过 Javascript来控制过渡动画,首先理解过渡的时机,动画分为进入离开进入有:进入前进入进入后,同样离开: 离开前离开离开后,那么在不同时机中,触发JavaScript 逻辑即可;

<transition> 对应的事件:

  • @before-enter:进入之前
  • @before-leave:离开之前
  • @enter:进入时
  • @leave:离开时
  • @after-enter:进入之后
  • @after-leave:离开之后
  • @enter-cancelled:进入中断
  • @leave-cancelled (v-show only):离开中断
template 复制代码
<template>
 <transition 
    @before-enter="EnterFrom"
    @enter="EnterActive"
    @after-enter="EnterTo"
    @enter-cancelled="EnterCancel"
    @before-leave="LeaveFrom"
    @leave="LeaveActive"
    @after-leave="LeaveTo"
    @leave-cancelled="LeaveCancel" >
    <div v-if="flag" class="box">8个 生命周期</div> 
</transition>
</template>
<script setup lang='ts'>
    // 进入
    const EnterFrom = (el:Element) => {
        console.log('动画进入之前EnterFrom');
    }
    const EnterActive = (el:Element, done: gsap.Callback) => {
        console.log('进入时 EnterActive');
    }
    const EnterTo = (el:Element) => {
        console.log(el,'动画进入之后 EnterTo');

    }
    const EnterCancel = (el:Element) => {
        console.log(el,'动画进过渡效果 被打断时 EnterCancel');
    }
    
    // 离开
    // el DOM 节点
    const LeaveFrom = (el:Element) => {
        console.log(el, '动画离开之前LeaveFrom');
    }
    const LeaveActive = (el:Element, done:Function) => {
        console.log(el,'离开时 LeaveActive');
        done()
    }
    const LeaveTo = (el:Element) => {
        console.log(el,'动画离开之后 LeaveTo');
    }
    const LeaveCancel = (el:Element) => {
        console.log(el,'动画离开过渡效果 被打断时------');
    }
    


</script>

过渡进入时触发:

过渡离开时触发: 过渡中断是什么时候出发呢,当进入过程中立马切换为离开时就会触发中断的函数了;当理解了出发函数钩子的时机,可以结合优秀的动画库,精准的实现效果;

2、<transition-group> 标签

单节点动画可以使用<transition>,多节点可以使用 <transition-group>;

特点:

  • 默认情况下 它不会渲染一个包裹元素,但是可以通过tag attribute 指定渲染一个元素, <transition-group tag="div"><transition tag="section"> 实际生成DOM标签divsection 包一层;
  • 过渡模式下不可用, 因为我们不再相互切换特有的元素
  • 内部元素 总是需要提供一个唯一的 key attribute值
  • CSS过渡的类型将会应用在内部的元素中,而不是这个组/容器本身

列表的移动过渡示例:

vue3 复制代码
<template>
   <!-- 列表的移动过度示例 
   技术点: <transition-group> 组件还有一个特殊之处除了进入和离开,transition-group还可以为定位的改变添加动画
         第三方库: lodash  npm install lodash --S  注意在ts 下 还需要安装类型声明文件库 npm i --save-dev @types/lodash
-->
 <div>
    <button @click="random">random</button>
    <transition-group move-class="move" class="wrap" 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' // 需要安装声明文件 npm i -D @types/lodash

let list = ref(Array.apply(null, {length:81} as number[]).map((_, index) => {
    return {
        id: index,
        number: (index % 9) + 1
    }
}))

console.log(list, 'list');
const random = () => {
    list.value = _.shuffle(list.value)
}
</script>
<style scoped lang="scss">
.wrap {
    display: flex;
    flex-wrap: wrap;
    width: calc(25px * 9 + 9px);
    .item {
        width: 25px;
        height: 25px;
        border: 1px solid #ccc;
        display: flex;
        justify-self: center;
        align-items: center;
    }
}
.move {
    transition: all 1s;
}
</style>

状态的过渡:

vue3 复制代码
<template>
   <input type="number" step="20" v-model="num.current">
       <div style="font-size: 30px; margin-left: 20px;">{{ num.tweenedNumber.toFixed() }}
       </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>
 

3、总结

主要理解<Transition><TransitionGroup>,同时结合动画库来实现过渡效果;

参考资料: Vue3文档 Vue3 知识系列 小满zs animate 动画库 gsap 动画库

相关推荐
隐形喷火龙2 分钟前
element ui--下拉根据拼音首字母过滤
前端·vue.js·ui
Simaoya1 小时前
【vue】css模拟玻璃球体效果(带高光)
前端·css·vue.js
ekskef_sef2 小时前
前端Vue框架基础介绍
前端·javascript·vue.js
椒盐大肥猫2 小时前
vue3 Proxy替换vue2 defineProperty的原因
前端·javascript·vue.js
旭久3 小时前
vue-计算两个日期之前的天数小方法
前端·javascript·vue.js
游王子3 小时前
Vue.js组件(6):echarts组件
前端·vue.js·echarts
苹果酱05675 小时前
Golang的文件解压技术研究与应用案例
java·vue.js·spring boot·mysql·课程设计
谢道韫6666 小时前
今日总结 2024-12-24
javascript·vue.js·elementui
racerun7 小时前
vue VueResource & axios
前端·javascript·vue.js
Calm5508 小时前
Vue3:uv-upload图片上传
前端·vue.js