封装ElLoading

193 阅读1分钟

封装效果

封装前

<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;