一、效果描述
在一个div中使用该指令并绑定一个变量,通过修改变量实现Loading的显示与隐藏。
二、代码与使用方式
1.使用指令的vue组件
<template>
<div v-loading="showLoading">
</div>
</template>
<script setup lang="ts">
import axios from "axios";
import { onMounted, ref } from "vue";
import { vLoading } from "../components/loadings/loding";
const showLoading = ref(false);
const getData = () => {
showLoading.value = true;
axios.get("接口地址").then((res) => {
showLoading.value = false;
});
};
onMounted(() => {
getGongneng();
});
2.TS文件
import { createApp } from "vue";
//含有loding样式的组件
import loadingOne from "./loadingOne.vue";
//存储每个元素的loading状态
const map = new WeakMap();
const createAndShowLoadingAnimation = (container: HTMLElement) => {
const loadingDivInstance = createApp(loadingOne);
loadingDivInstance.mount(container);
container.style.display = "block";
};
const hideLoadingAnimation = (container: HTMLElement) => {
container.style.display = "none";
};
//自定义指令
export const vLoading = {
mounted(el: HTMLElement, binding: any) {
//创建一个div容器并添加到使用指令的元素中
const loadingDivContainer = document.createElement("div");
loadingDivContainer.className = "loading-container";
loadingDivContainer.style.display = "none";
loadingDivContainer.style.margin = "0 auto";
loadingDivContainer.style.marginTop = "100px";
el.appendChild(loadingDivContainer);
//根据传入的值决定是否显示loading动画
if (binding.value) {
createAndShowLoadingAnimation(loadingDivContainer);
}
//将元素和loading状态存储到map中
map.set(el, { loadingDivContainer, value: binding.value });
},
updated(el: HTMLElement, binding: any) {
//获取元素的loading状态
const { loadingDivContainer, value: oldValue } = map.get(el) || {};
//如果传入的值和之前的值不一样,则更新loading状态
if (binding.value !== oldValue) {
if (binding.value) {
createAndShowLoadingAnimation(loadingDivContainer);
} else {
hideLoadingAnimation(loadingDivContainer);
}
map.set(el, { loadingDivContainer, value: binding.value });
}
},
unmounted(el: HTMLElement) {
const { loadingDivContainer } = map.get(el) || {};
if (loadingDivContainer) {
hideLoadingAnimation(loadingDivContainer);
map.delete(el);
}
},
};
3.自定义一个loading样式
<template>
<div id="load">
<div class="loader loader--style1" title="0">
<svg
version="1.1"
id="loader-1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px"
y="0px"
width="100px"
height="100px"
viewBox="0 0 40 40"
enable-background="new 0 0 40 40"
xml:space="preserve"
>
<path
opacity="0.2"
fill="#000"
d="M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946,14.946,14.946
s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201,5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634
c0-6.425,5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834,26.541,26.626,31.749,20.201,31.749z"
/>
<path
fill="#000"
d="M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0
C22.32,8.481,24.301,9.057,26.013,10.047z"
>
<animateTransform
attributeType="xml"
attributeName="transform"
type="rotate"
from="0 20 20"
to="360 20 20"
dur="0.5s"
repeatCount="indefinite"
/>
</path>
</svg>
</div>
</div>
</template>
<style scoped lang="scss">
.loader {
svg path,
svg rect {
fill: #ff6700;
}
}
</style>