创建自定义指令
指令会根据传入的参数控制加载动画的显示状态,并动态更新动画的大小和颜色。
创建加载动画实例
首先,创建一个 createLoading.ts
文件,用于管理加载动画的创建、更新和销毁:
// createLoading.ts
import { createVNode, defineComponent, h, reactive, render } from "vue";
import Loading from "./Loading.vue";
export function createLoading(props: any, target: HTMLElement) {
const data = reactive({ ...props });
const Comp = defineComponent({
render: () => h(Loading, data),
});
const vm = createVNode(Comp);
const container = document.createElement("div");
render(vm, container);
target.appendChild(vm.el as HTMLElement);
return {
update: (newProps: any) => Object.assign(data, newProps),
destroy: () => render(null, container),
};
}
加载动画组件
创建一个 Loading.vue
文件,用于展示加载动画:
<!-- Loading.vue -->
<script setup lang="ts">
import { computed } from "vue";
const props = defineProps({
isVisible: {
type: Boolean,
default: true,
},
size: {
type: Number,
default: 30,
},
color: {
type: String,
default: "#25b09b",
},
});
const sizePx = computed(() => props.size + "px");
</script>
<template>
<div class="loader-box" v-if="isVisible">
<div class="loader" :style="{ width: sizePx, height: sizePx, background: color }"></div>
</div>
</template>
<style scoped>
.loader-box {
display: flex;
width: 100%;
height: 100%;
justify-content: center;
align-items: center;
}
.loader {
padding: 4px;
border-radius: 50%;
animation: rotate 1s infinite linear;
}
@keyframes rotate {
to {
transform: rotate(1turn);
}
}
</style>
定义指令逻辑
然后,在 loadingDirective.ts
文件中,定义 v-loading
指令的核心逻辑:
// loadingDirective.ts
import { createLoading } from "./createLoading";
interface DirectiveEl extends HTMLElement {
__loadingInstance: any;
}
export const loadingDirective: Directive = {
mounted(el: DirectiveEl, binding: DirectiveBinding<boolean>) {
const props = {
isVisible: binding.value,
size: el.getAttribute("loading-size") || 30,
color: el.getAttribute("loading-color") || "#25b09b",
};
const instance = createLoading(props, el);
el.__loadingInstance = instance;
},
updated(el: DirectiveEl, binding: DirectiveBinding<boolean>) {
const props = {
isVisible: binding.value,
size: el.getAttribute("loading-size") || 30,
color: el.getAttribute("loading-color") || "#25b09b",
};
el.__loadingInstance.update(props);
},
unmounted(el: DirectiveEl) {
el.__loadingInstance.destroy();
},
};
注册与使用指令
最后,我们需要在 Vue 应用中注册自定义指令,以便在模板中使用。
注册指令
创建一个 registerDirective.ts
文件,用于注册自定义指令:
// registerDirective.ts
import { loadingDirective } from "./loadingDirective";
export function registerDirective(app: any) {
app.directive("loading", loadingDirective);
}
主应用入口
在主应用入口文件 main.ts
中,导入并调用 registerDirective
来注册指令:
// main.ts
import { createApp } from "vue";
import App from "./App.vue";
import { registerDirective } from "./registerDirective";
const app = createApp(App);
registerDirective(app);
app.mount("#app");
总结
通过以上三个步骤,我们成功创建了一个自定义的 v-loading
指令,用于在 Vue 应用中控制加载动画的显示与隐藏。这个指令不仅使用方便,还能灵活地自定义加载动画的样式。