近期重点复盘了 Vue3 的部分知识点,主要是过渡动画 和自定义指令两大模块。其中自定义指令在实际开发中(如防抖、节流)高频使用,该篇主要讲解;过渡动画则是提升用户体验的基础,也会结合案例梳理核心逻辑。
一、Vue3 过渡动画(transition 组件)(⭐)
在 Vue 中,transition 是内置的过渡动画组件,能为元素的插入/移除(如v-if/v-show 控制)添加流畅的动画效果,核心是通过预设的 CSS 类名控制动画的**[进入/离开]**状态。
1. 核心原理
transition 组件会在元素进入 / 离开 DOM 时,自动为元素添加 / 移除一系列以[动画名称]为前缀的 CSS 类名,我们只需通过这些类名定义动画的起始、过程、结束状态。
核心 CSS 类名(以**name="fade"**为例):
| 类名 | 作用 |
|---|---|
fade-enter-from |
进入动画的初始状态(进入前) |
fade-enter-active |
进入动画的执行状态(进入中) |
fade-enter-to |
进入动画的结束状态(进入后) |
fade-leave-from |
离开动画的初始状态(离开前) |
fade-leave-active |
离开动画的执行状态(离开中) |
fade-leave-to |
离开动画的结束状态(离开后) |
2. 实战案例:元素显隐动画
TypeScript
<template>
<div>
<button @click="visible = !visible">显示/隐藏</button>
<!-- appear:控制初始渲染时也触发动画 -->
<transition appear name="fade">
<div class="box" v-if="visible"></div>
</transition>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const visible = ref(true) // 控制元素显隐
</script>
<style scoped>
.box {
width: 200px;
height: 200px;
background-color: rgb(178, 147, 147);
}
/* 进入的初始状态/离开的最终状态 */
.fade-enter-from {
opacity: 0; /* 透明 */
transform: translateX(-20px); /* 左移20px */
}
.fade-leave-to {
opacity: 0; /* 透明 */
transform: translateX(20px); /* 右移20px */
}
/* 动画执行过程(缓动效果) */
.fade-enter-active, .fade-leave-active {
transition: all 0.5s ease;
}
/* 进入的最终状态/离开的初始状态 */
.fade-enter-to, .fade-leave-from {
opacity: 1; /* 不透明 */
transform: translateX(0); /* 回到原位置 */
}
</style>
代码所示这种效果当你点击按钮,box从显性---->隐身时会有一个消失动画,box会向右缓动平移20px的距离消失
小结
- **
appear**属性让元素初始渲染时也触发动画; - 动画的核心是「状态切换」,通过 CSS 过渡属性
transition控制动画时长和缓动效果; transition仅包裹单个元素,若需多个元素 / 组件过渡,可使用transition-group。
二、Vue3 自定义指令(⭐⭐⭐⭐⭐)
Vue 内置指令(如v-if,v-bind)满足日常开发,但实际场景中(防抖、节流、图片懒加载等)需要自定义指令封装通用逻辑。Vue3 中自定义指令分为「局部指令」和「全局指令」,接下来以「全局防抖指令 v-debounce」为例拆解。
1. 自定义指令的核心概念
自定义指令本质是一个包含生命周期钩子的对象,核心钩子包括:
- mounted:指令绑定到元素且元素挂载到 DOM 时触发(常用);
- beforemount:指令绑定的元素卸载前触发(用于清理定时器 / 事件监听);
指令钩子的核心参数(⭐⭐⭐):
el:指令绑定的DOM 元素(可直接操作 DOM,如添加事件监听、修改样式);
binding:指令的[信息对象],包含:
arg:指令参数(如v-debounce:1000中的1000);value:指令绑定的值(如v-debounce="clickHandler"中的clickHandler);modifiers:指令修饰符(如v-debounce.stop中的stop);
下文有二者的输出可更有益于理解二者
2. 实战:全局防抖指令**v-debounce**
2.1 需求背景
按钮点击时若频繁触发事件(如提交表单),会增加服务器压力,通过防抖指令限制[n 毫秒内仅执行一次点击事件]
2.2 全局注册自定义指令(main.ts)
TypeScript
import { createApp } from 'vue'
import App from './study_tree/组件化开发/19.内置组件/30.自定义指令.vue'
const app = createApp(App)
// 全局注册 v-debounce 指令
app.directive('debounce', {
//查看二者详情
console.log("el", el, "binding", binding);
// 指令绑定元素并挂载后触发
mounted(el: HTMLElement, binding) {
let timer = null // 存储定时器ID
// 防抖时间:优先取指令参数(如v-debounce:1000),默认500ms
const timeout = binding.arg || 500
// 为元素添加点击事件监听
el.addEventListener('click', () => {
// 若已有定时器,清除(重置防抖计时)
if (timer) clearTimeout(timer)
// 延迟执行绑定的事件处理函数
timer = setTimeout(binding.value, timeout)
})
// 示例:给元素挂载定时器(仅演示,实际防抖无需)
el.timer = setInterval(() => {
console.log('定时器示例')
}, 1000)
},
// 元素卸载前清理资源(避免内存泄漏)
beforeUnmount(el: HTMLElement) {
// 清除定时器
clearTimeout(el.timer)
// 移除事件监听(避免重复触发)
el.removeEventListener('click', el.clickHandler)
}
})
app.mount('#app')
2.3 使用自定义指令(组件中)
TypeScript
<template>
<div>
<button @click="visible = !visible">切换可见性</button>
<button @click="clickHandler">不带防抖</button>
<!-- 使用v-debounce,参数1000表示防抖1秒 -->
<button v-debounce:1000="clickHandler" v-if="visible">带防抖 1s</button>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const visible = ref(true)
// 点击事件处理函数
function clickHandler() {
console.log("点击了按钮(防抖后执行)")
}
</script>
2.4 控制台截图

3. 核心逻辑拆解(⭐⭐⭐)
3.1 mounted钩子的防抖逻辑
- 初始化 **
timer**存储定时器 ID,避免重复计时; - 通过**
binding.arg** 获取防抖时间(无参数则默认 500ms); - 给元素绑定点击事件:
- 若已有定时器,先清除(重置防抖);
- 新建定时器,延迟
timeout毫秒执行binding.value(即绑定的点击函数)。
3.2 beforeUnmount 钩子的资源清理
- 清除
el.timer(避免定时器残留导致内存泄漏); - 移除元素的点击事件监听(避免卸载后事件仍触发);
3.3 参数使用
el:直接操作 DOM 的入口,比如el.addEventListener绑定事件、el.timer挂载自定义属性;binding.arg:灵活传递防抖时间,比如v-debounce:500对应 500ms,v-debounce:1000对应 1 秒;binding.value:接收组件中传递的[事件处理函数],是指令和组件逻辑的桥梁。
三、 总结
- 过渡动画:通过
transition组件 + CSS 类名控制元素显隐动画,核心是[状态切换]和[过渡属性],**appear**属性解决初始渲染无动画问题; - 自定义指令:
- 核心是[操作 DOM + 封装通用逻辑],
mounted钩子绑定逻辑,**beforeUnmount**钩子清理资源; el是操作 DOM 的入口,binding是指令与组件通信的桥梁(arg传参数、value传回调);- 防抖指令是高频场景,需注意「定时器清理」避免内存泄漏。
- 核心是[操作 DOM + 封装通用逻辑],
这一节的内容需要动手+思考 理清思路,废话不多说,"动手吧"!