项目场景:
公司项目中使用element-plus的loading效果时想更改默认的loading图标
问题描述
遗憾的是el-config-provider没有对应的全局配置属性,无法通过全局配置简单实现。
解决方案:
第一时间想到用覆盖样式的方式解决,但思考之后觉得不是很完美,于是研究了第二套方案,废话不多说,直接上代码。
方案一:
大致就是将图中svg标签隐藏掉,给el-loading-spinner类添加before或after,再结合自定义的样式和动画实现loading效果。
方案二:
通过重写ElLoading的方式实现,具体如下:
1、在plugins文件夹下新建wrapElLoading.ts文件
wrapElLoading.ts
import {ElLoading} from "element-plus";
/**
* @description 扩展ElLoading,传入默认值
*/
export default {
install(app: any) {
const svg: string = `<path d="M21.38,4.58a4.62,4.62,0,0,0,9.24,0h0a4.62,4.62,0,0,0-9.24,0Z" fill="#9ab1c9"/><path d="M6.33,10.39a3.75,3.75,0,0,0,7.49,0h0a3.75,3.75,0,0,0-7.49,0Z" fill="#9ab1c9"/><path d="M0,25.86a3.43,3.43,0,0,0,6.86,0h0a3.41,3.41,0,0,0-3.43-3.4A3.41,3.41,0,0,0,0,25.85Z" fill="#9ab1c9"/><path d="M6.88,41.66a3.2,3.2,0,1,0,3.2-3.17A3.18,3.18,0,0,0,6.88,41.66Z" fill="#9ab1c9"/><path d="M23.32,47.35a2.68,2.68,0,0,0,5.36,0h0a2.68,2.68,0,0,0-5.36,0Z" fill="#9ab1c9"/><path d="M39.68,41.66a2.14,2.14,0,0,0,4.28,0h0a2.14,2.14,0,0,0-4.28,0Z" fill="#9ab1c9"/><path d="M46.85,26A1.58,1.58,0,0,0,50,26h0a1.58,1.58,0,0,0-3.15,0Z" fill="#9ab1c9"/><path d="M40.77,10.2a1.12,1.12,0,1,0,1.12-1.11A1.12,1.12,0,0,0,40.77,10.2Z" fill="#9ab1c9"/>`;
const loadingDir: any = ElLoading.directive
const originDirMounted = loadingDir.mounted;
loadingDir.mounted = function (el: any, binding: any, vnode: any, prevVnode: any) {
// 需要覆盖哪些默认属性值在这里设置,具体属性名参考官网loading指令用法
el.setAttribute('element-loading-svg', svg)
originDirMounted.call(this, el, binding, vnode, prevVnode)
}
const originService = ElLoading.service;
ElLoading.service = function (options: any = {}) {
return originService.call(this, Object.assign({ svg}, options))
}
app.config.globalProperties.$loading = ElLoading.service;
// 如果在main.ts中全局使用了ElementPlus —> app.use(ElementPlus),则下面这行代码不需要
// app.use(ElLoading);
}
}
2、在main.ts中use即可
import WrapElLoading from "@/plugins/wrapElLoading";
// 若项目采用全局引入ElementPlus,则须在app.use(ElementPlus)后执行
app.use(WrapElLoading);
3、在组件中使用:
<template>
<div class="about">
<el-button @click="showLoading">show loading</el-button>
<el-button @click="manualLoading">manual loading</el-button>
<div v-loading="loading" element-loading-text="加载中……" class="loading-wrap"></div>
<div ref="manualLoadingRef" class="loading-wrap"></div>
</div>
</template>
<script setup lang="ts">
import {getCurrentInstance, ref} from "vue";
const ctx: any = getCurrentInstance()?.appContext.config.globalProperties
const loading = ref(false);
const manualLoadingRef = ref();
function showLoading() {
loading.value = !loading.value
}
function manualLoading() {
const loadingIns = ctx.$loading({target: manualLoadingRef.value})
setTimeout(() => {
loadingIns.close()
}, 2000)
}
</script>
<style lang="scss" scoped>
.about {
border: 1px solid #42b983;
height: 100%;
padding: 60px;
.loading-wrap {
width: 200px;
height: 200px;
border: 1px solid #ccc;
}
}
</style>