封装效果
封装前
<script setup>
import { ref } from 'vue';
import listApi from '@/api';
import { ElLoading } from 'element-plus';
const list = ref([]);
async function getList() {
const loading = ElLoading.service({text:'请稍后'});
try{
const { data } = await listApi({page:1});
list.value = data;
} catch (err){
loading.close();
throw err;
}
}
</script>
封装后
<script setup>
import { ref } from 'vue';
import withLoading from '@/utils/loading';
import listApi from '@/api';
const list = ref([]);
async function getList() {
const { data } = await withLoading(listApi)({page:1});
list.value = data;
}
</script>
封装后简洁了很多,使用起来也很方便,这里重点就是withLoading函数,直接看是如何实现的:
withLoading
import { ElLoading } from 'element-plus';
// 默认配置
const defaultOption = {
lock: true,
text: '请稍候...'
}
// 默认loading最少持续时间ms
const defaultLeastTime = 200;
/**
* loading
* @param {function} fn 远程请求方法
* @param {object} options loading配置对象
* @param {number} leastTime 最少持续时间ms
* @returns {function}
*/
const withLoading = (fn, options = {}, leastTime) => {
let start;// 开始时间
const lt = leastTime || defaultLeastTime;// 最少持续时间ms
// loading实例
let loading;
// 打开loading
const showLoading = (opt) => {
start = Date.now();
loading = ElLoading.service(opt);
}
// 关闭loading
const hideLoading = () => {
if (!loading) return;
const diff = Date.now() - start;// 从开始结束实际经过时间
if (diff < lt) {
setTimeout(() => {
loading.close();
loading = null;
}, lt - diff)
} else {
loading.close();
loading = null;
}
}
// 新的配置
const _options = { ...defaultOption, ...options };
return (...args) => {
try {
showLoading(_options);
const result = fn(...args);
// 如果fn返回结果不是Promise,就直接返回result
const isPromise = result instanceof Promise;
if (!isPromise) {
hideLoading();
return result;
}
return result
.then(res => {
hideLoading();
return res;
}).catch(err => {
hideLoading();
throw err;
})
} catch (err) {
hideLoading();
throw err;
}
}
}
export default withLoading;