vue3 v-loading指令封装

1,918 阅读1分钟

最近用 Arco Design 发现它除了button组件,其他并没有封装v-loading的指令,遂自己封装之

思路是先做个loading状态的hook,然后封装v-loading指令用于控制

Loading hook封装

//文件新建 src/hooks/useLoading.ts
import { ref } from 'vue';
export default function useLoading() {
    const loading = ref<boolean>(false);
    const setLoading = (type:boolean)=>{
        loading.value = type;
    }
  return {
      setLoading,
      loading
  };
}

v-loading 指令封装

// 新建文件  src/directives/loading/index.vue
<template>
  <div class="loading-container">
    <icon-loading />
  </div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { IconLoading } from '@arco-design/web-vue/es/icon';
export default defineComponent({
  components:{
    IconLoading
  },
  setup() {
    
  },
});
</script>
<style lang="scss" scoped>
.loading-container{
    position: absolute;
    left: 0;
    top: 0;
    height: 100%;
    width: 100%;
    overflow: hidden;
    background: rgba($color: #ffffff, $alpha: 0.7);
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 50px;
    color: #335dfd;
}
</style>
// 新建文件  src/directives/loading/index.ts

import {createApp, Directive } from 'vue';
import Loading from './index.vue';

const loading: Directive = {
  mounted(el,binding){
    const app = createApp(Loading);
    const instance = app.mount(document.createElement('div'));
    el.instance = instance;
    el.style.position = 'relative';
    if (binding.value) {
      appendEl(el);
    }
  },
  updated(el,binding) {
    if (binding.value !== binding.oldValue) {
      binding.value ? appendEl(el) : removeEl(el); 
    }
  },
};

const appendEl = (el: { appendChild: (arg0: any) => void; instance: { $el: any; }; }) =>{
  el.appendChild(el.instance.$el);
};

const removeEl = (el: { removeChild: (arg0: any) => void; instance: { $el: any; }; }) =>{
  el.removeChild(el.instance.$el);
};

export default loading;

// src/main.ts 导入

import { createApp } from "vue";
import App from "./App.vue";

import loading from '@/directives/loading';
const app = createApp(App);

// 全局指令的使用
app.directive('loading',loading);

app.mount("#app");

在组件中使用

<template>
 <div class="testBox"  v-loading="loading">加载测试</div>
</template>

<script lang="ts">
import { defineComponent, ref,} from "vue";
import useLoading from '@/hooks/useLoading';
export default defineComponent({
  setup() {
    const {loading,setLoading} = useLoading();
    setLoading(true);
    setTimeout(() => {
      setLoading(false);
    }, 5000);
    return {
      loading
    };
  }
});
</script>

<style lang="scss" scoped>
.testBox{
  display: block;
  padding: 50px;
  text-align: center;
  text-align: center;
}
</style>