Vue 3 自定义指令实现 loading 加载效果
在前端开发中,有时我们需要在页面加载数据或执行特定操作时,展示一个加载动画或遮罩层来提升用户体验。在 Vue 应用中,通过自定义指令可以非常方便地实现这样的功能,同时保持代码的可维护性和可复用性。
关于 vue3 自定义指令的介绍与使用,可以先看一下 Vue 3 自定义指令简解
本demo地址:github.com/baozjj/vue-…
效果演示
只需要在元素中使用 v-loading 自定义指令即可实现:
<template>
<Button @click="isLoading = !isLoading"> 加载 </Button>
当前状态: {{ isLoading }}
<div
style="
width: 200px;
height: 100px;
border-radius: 5px;
border: 1px solid black;
margin-top: 10px;
"
v-loading="isLoading"
>
我是内容
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const isLoading = ref(false)
<script>
实现步骤
文件结构
在开始之前,让我们先来看一下项目的文件结构:
my-vue-directives/
│
├── src/
│ ├── directives/
│ │ ├── loading/
│ │ │ ├── index.ts // 定义加载动画自定义指令的逻辑
│ │ │ └── style.css // 定义加载动画的样式
│ │ ├── index.ts // 批量注册自定义指令
│ │ └── style.css // 公共样式
│ ├── App.vue // 根组件
│ └── main.ts // 入口文件,初始化Vue实例
创建自定义指令
首先,在 src/directives/loading/
文件夹中创建一个新的文件 index.ts
,用于定义加载动画自定义指令的逻辑:
import type { DirectiveBinding } from 'vue'
interface ElType extends HTMLElement {
overlay: HTMLElement | null
}
const loadingDirective = {
// 在元素挂载时调用
mounted(el: ElType, binding: DirectiveBinding) {
// 创建遮罩层
const overlay = document.createElement('div')
overlay.className = 'directives-loading-overlay' // 稍后在样式文件中定义
overlay.style.display = 'none'
// 创建 中间旋转 的元素
const spinner = document.createElement('div')
spinner.className = 'directives-loading-spinner' // 稍后在样式文件中定义
overlay.appendChild(spinner)
el.overlay = overlay
el.style.position = 'relative' // 设置相对定位
el.appendChild(overlay)
// 根据元素的大小设置加载动画的尺寸
const size = Math.min(Math.min(el.clientWidth, el.clientHeight) / 2, 30)
spinner.style.width = `${size}px`
spinner.style.height = `${size}px`
spinner.style.borderWidth = `${size / 10}px`
if (binding.value) {
el.overlay!.style.display = 'flex'
el.classList.add('directives-loading-active') // 稍后在样式文件中定义
} else {
el.overlay!.style.display = 'none'
}
},
// 在绑定值更新时调用
updated(el: ElType, binding: DirectiveBinding) {
// 根据绑定值的变化显示或隐藏加载效果
if (binding.value) {
el.overlay!.style.display = 'flex'
el.classList.add('directives-loading-active')
} else {
el.overlay!.style.display = 'none'
el.classList.remove('directives-loading-active')
}
},
unmounted(el: ElType) {
// 移除加载元素
el.removeChild(el.overlay!);
el.overlay = null;
}
};
export default loadingDirective;
添加样式
接下来,在 src/directives/loading/
文件夹中创建一个 style.css
文件,用于定义遮罩层和加载动画的样式:
/* 遮罩层 */
.directives-loading-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(193, 191, 191, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 999;
}
/* 旋转元素 */
.directives-loading-spinner {
justify-content: center;
align-items: center;
width: 50px;
height: 50px;
border: 5px solid rgba(0, 0, 0, 0.5);
border-radius: 50%;
border-left-color: transparent;
animation: loading-spin 1s linear infinite;
}
/* loading 状态时添加 */
.directives-loading-active {
overflow: hidden;
pointer-events: none; /* 禁止事件 */
}
@keyframes loading-spin {
to {
transform: rotate(360deg);
}
}
批量注册自定义指令
在 src/directives/
文件夹中创建一个 index.ts
文件,用于批量注册自定义指令:
import type { App, Directive } from 'vue';
import loadingDirective from './loading/index';
// 其他指令
const directives: { [key: string]: Directive } = {
loading: loadingDirective,
// 其他指令
};
export default {
install(app: App) {
Object.keys(directives).forEach(key => {
app.directive(key, directives[key]);
});
}
};
并在 src/directives/
文件夹中创建一个 style.css
文件,用于导入所有自定义指令的样式:
@import './loading/style.css';
/* 其他指令需要的样式 */
入口文件
// src/main.ts
import { createApp } from 'vue';
import App from './App.vue';
// 导入自定义指令以及样式
import directives from './directives';
import './directives/style.css'
const app = createApp(App);
app.use(directives);
app.mount('#app');
结语
通过以上步骤,就成功实现了一个可以在 Vue 3 项目中使用的简易的加载效果自定义指令。如果有任何疑问或建议,欢迎留言交流!