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 动画库

相关推荐
Zhencode7 分钟前
Vue3 响应式依赖收集与更新之effect
前端·vue.js
天下代码客29 分钟前
使用electronc框架调用dll动态链接库流程和避坑
前端·javascript·vue.js·electron·node.js
weixin79893765432...2 小时前
Vue 渲染体系“三件套”(template 模板语法、h 函数和 JSX 语法)
vue.js·h函数·template 模板·jsx 语法
xkxnq2 小时前
第五阶段:Vue3核心深度深挖(第74天)(Vue3计算属性进阶)
前端·javascript·vue.js
Hilaku2 小时前
不要在简历上写精通 Vue3?来自面试官的真实劝退
前端·javascript·vue.js
竟未曾年少轻狂3 小时前
Vue3 生命周期钩子
前端·javascript·vue.js·前端框架·生命周期
TT哇3 小时前
【实习】数字营销系统 银行经理端(interact_bank)前端 Vue 移动端页面的 UI 重构与优化
java·前端·vue.js·ui
用户982450514183 小时前
vue3响应式解构注意
vue.js
不会敲代码13 小时前
🚀 从DOM操作到Vue3:一个Todo应用的思维革命
vue.js
未来龙皇小蓝4 小时前
RBAC前端架构-02:集成Vue Router、Vuex和Axios实现基本认证实现
前端·vue.js·架构