如何实现一个Element的loading组件

955 阅读1分钟

这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战

image.png

初始化vue项目

vue create vue-loading @vitejs/app

Element-plus 中 loading组件的使用

首先我们来看一下在 Element-plus 中 loading组件的使用

安装

npm install element-plus --save

引入

在 main.js 中写入以下内容

import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/lib/theme-chalk/index.css'

const app = createApp(App)
app.use(ElementPlus)
app.mount('#app')

使用


<template>
    <el-table
      v-loading="loading"
      :data="tableData"
      style="width: 100%">
      <el-table-column
        prop="date"
        label="日期"
        width="180">
      </el-table-column>
      <el-table-column
        prop="name"
        label="姓名"
        width="180">
      </el-table-column>
      <el-table-column
        prop="address"
        label="地址">
      </el-table-column>
    </el-table>
  </template>
  
  <script>
    import { defineComponent, reactive, toRefs } from 'vue';
  
    export default defineComponent({
      setup() {
        const state = reactive({
          tableData: [
            {
              date: '2016-05-03',
              name: '王小虎',
              address: '上海市普陀区金沙江路 1518 弄',
            },
            {
              date: '2016-05-02',
              name: '王小虎',
              address: '上海市普陀区金沙江路 1518 弄',
            },
            {
              date: '2016-05-04',
              name: '王小虎',
              address: '上海市普陀区金沙江路 1518 弄',
            },
          ],
          loading: true,
        });
        return {
          ...toRefs(state),
        };
      },
    });
  </script>
  <style>
    body {
      margin: 0;
    }
  </style>

element-plus loading的更多使用见文档详情 element-plus.gitee.io/#/zh-CN/com…

如何自定义实现一个 loading组件

在components目录下新建一个 Loader.vue 组件

这里为了快速的搭建页面和缩短写 css的时间,引入了 bootstrap

安装最新版的 Bootstrap

 npm install bootstrap@next --save

Bootstrap V5 文档地址: v5.getbootstrap.com/

在 main.js 中引入 css文件

// 引入 bootstrap 样式
import 'bootstrap/dist/css/bootstrap.min.css';

基础组件

Loader.vue

<template>
        <div
            class="d-flex justify-content-center align-items-center h-100 loading-container"
            
        >
            <div class="loading-content">
                <div class="spinner-border text-primary" role="status">
                    <span class="visually-hidden"> Loading...</span>
                </div>
                <p class="text-primary small">拼命加载中</p>
            </div>
        </div>
</template>

<script>
import { defineComponent, onUnmounted } from 'vue';
export default defineComponent({
    props: {
        text: {
            type: String
        },
        background: {
            type: String
        }
    },
    setup() {
        const node = document.createElement('div');
        node.id = 'back';
        document.body.appendChild(node);
        onUnmounted(() => {
            document.body.removeChild(node);
        });
    }
});
</script>

深入实现

现在我们已经可以看到这个组件的样子了,为了更加可用,我们还需要封装以下

<template>
    <teleport to="#back">
        <div
            class="d-flex justify-content-center align-items-center h-100 loading-container"
            :style="{backgroundColor: background || ''}"
        >
            <div class="loading-content">
                <div class="spinner-border text-primary" role="status">
                    <span class="visually-hidden">{{text || 'Loading...'}}</span>
                </div>
                <p v-if="text" class="text-primary small">{{text}}</p>
            </div>
        </div>
    </teleport>
</template>

<script>
import { defineComponent, onUnmounted } from 'vue';
export default defineComponent({
    props: {
        text: {
            type: String
        },
        background: {
            type: String
        }
    },
    setup() {
        const node = document.createElement('div');
        node.id = 'back';
        document.body.appendChild(node);
        onUnmounted(() => {
            document.body.removeChild(node);
        });
    }
});
</script>
<style>
.loading-container {
    background: rgba(255, 255, 255, 0.5);
    z-index: 100;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}
.loading-content {
    text-align: center;
}
</style>

使用axios 拦截器添加 loading 效果

// http 请求拦截
axios.interceptors.request.use((config) => {
    store.commit('setLoading', true);
    return config;
});

axios.interceptors.response.use((config) => {
    store.commit('setLoading', false);
    return config;
});

调用

<loader v-if="isLoading" text="拼命加载中……" background="rgba(0,0,0,.8)"></loader>