Vue 自定义指令 实现加载动画

创建自定义指令

指令会根据传入的参数控制加载动画的显示状态,并动态更新动画的大小和颜色。

创建加载动画实例

首先,创建一个 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 应用中控制加载动画的显示与隐藏。这个指令不仅使用方便,还能灵活地自定义加载动画的样式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值