VUE 全局loading,message组件封装

样式及逻辑自定,如下举例

loading:

loading.vue:

<template>
    <div  class="loading" id="vue-loading">
        <div class="loadEffect">
            <span></span>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
        </div>
    </div>
</template>

<script>
    export default {
        name: "loading",
    }
</script>

<style lang="stylus" scoped>
    @import "./loading.styl";
</style>

loading.js:

import LoadingComponents from './loading.vue';

let Loading = {};
Loading.installed = false;
Loading.install = (Vue) => {
    if (Loading.installed) return;
    Vue.prototype.$loading = {};
    Vue.prototype.$loading.show = () => {
        if (document.querySelector('#vue-loading')) return;
        let LoadingTip = Vue.extend(LoadingComponents);
        let tpl = new LoadingTip().$mount().$el;
        document.body.appendChild(tpl);
        document.querySelector('#vue-loading').addEventListener('touchmove', function (e) {
            e.stopPropagation()
            e.preventDefault()
        });
        Loading.installed = true;
    }
    Vue.prototype.$loading.hide = () => {
        let tpl = document.querySelector('#vue-loading');
        if(tpl) document.body.removeChild(tpl);
    }
}

export default Loading;

loading.styl:

.loading
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  margin: 0 auto;
  text-align: center;
  box-sizing: border-box;
  padding: 400px 0 0 0;
  background: rgba(255, 255, 255, 0.6);
  z-index: 1000;
  display: block;
.loadEffect
  width:200px;
  height:200px;
  position:relative;
  margin: 0 auto;
  box-sizing: border-box;
  padding: 0;

.loadEffect span
  display:inline-block;
  width:20px;
  height:20px;
  border-radius:50%;
  background: #089eff;
  position:absolute;
  -webkit-animation:load 1.04s ease infinite;
@-webkit-keyframes load
  0%
    opacity:1;
  100%
    opacity:0.2;
.loadEffect span:nth-child(1)
  left:0;
  top:50%;
  margin-top:-15px;
  -webkit-animation-delay:0.13s;
.loadEffect span:nth-child(2)
  left:25px;
  top: 25px;
  -webkit-animation-delay:0.26s;
.loadEffect span:nth-child(3)
  left:50%;
  top:0px;
  margin-left:-15px;
  -webkit-animation-delay:0.39s;
.loadEffect span:nth-child(4)
  top:25px;
  right:25px;
  -webkit-animation-delay:0.52s;
.loadEffect span:nth-child(5)
  right:0;
  top:50%;
  margin-top:-15px;
  -webkit-animation-delay:0.65s;
.loadEffect span:nth-child(6)
  right:25px;
  bottom:25px;
  -webkit-animation-delay:0.78s;
.loadEffect span:nth-child(7)
  bottom:0;
  left:50%;
  margin-left:-15px;
  -webkit-animation-delay:0.91s;
.loadEffect span:nth-child(8)
  bottom:25px;
  left:25px;
  -webkit-animation-delay:1.04s;

main.js:

import Loading from '@/components/loading/loading';


Vue.use(Loading);

 

 

message:alert:

alert.js:

import Alert from './alert.vue'
import Vue from 'vue'
let AlertConstructor = Vue.extend(Alert)
let instance,
    seed = 1,
    index = 2000;
const install = () => {
    Object.defineProperty(Vue.prototype, '$alert', {
        get () {
            let id = 'message_' + seed++
            const alertMsg = options => {
                instance = new AlertConstructor({
                    propsData: options
                })
                index++;
                instance.id = id;
                instance.vm = instance.$mount();
                document.body.appendChild(instance.vm.$el);
                instance.vm.$el.style.zIndex = index;
                return instance.vm;
            }
            return alertMsg
        }
    })
}
export default install

alert.styl:

.info
  position: fixed;
  top: 100px;
  min-height: 70px;
  height: auto;
  white-space: normal;
  word-break: break-all;
  box-sizing: border-box;
  padding: 0 30px;
  width: 500px;
  left: 50%;
  z-index: 9999;
  border: 1px solid #ebeef5;
  background: #edf2fc;
  color: #909399;
  line-height: 70px;
  border-radius: 15px;
  margin-left: -250px;
  transition: all .5s;
  font-size: 26px;
  text-align: left;
  &.success
    border: 1px solid #e1f3d8;
    background: #f0f9eb;
    color: #67c23a;
  &.error
    border: 1px solid #fde2e2;
    background: #fef0f0;
    color: #f56c6c;
  &.warning
    border: 1px solid #faecd8;
    background: #fdf6ec;
    color: #e6a23c;

alert.vue:

<template>
    <div
        class="info"
        :style="{top:`${top}px`}"
        :class="{'success':type === 'success','error': type === 'error','warning': type === 'warning'}"
        v-if="isShow"
    >
        {{msg}}
    </div>
</template>
<script>
    export default {
        /**
         * 参考: Vue : https://cn.vuejs.org/v2/guide/components.html
         * @param {string|number} msg 弹框内容
         * @param {String} type 弹出框类型  可选值有:'success'、'warning'、'info'、'error' 默认值为 'info'
         * @param {Number} time 弹出框关闭时间  以秒为单位 默认值为 2S
         * @param {String} top 弹出框高度 字符串类型数值  默认值为 '100'
         */
        props: {
            msg: {
                type: [String, Number],
                default: ''
            },
            type: {
                type: String,
                default: ''
            },
            time:{
                type: Number,
                default: 2,
            },
            top:{
                type: String,
                default: '100',
            }
        },
        mounted() {
            setTimeout(()=>this.msg = '',this.time*1000);
        },
        methods: {
        },
        computed: {
            isShow () {
                return Boolean(this.msg);
            }
        },
    }
</script>
<style lang="stylus" scoped>
    @import "./alert.styl"
</style>

main.js:


import Alert from '@/components/message/alert';


Vue.use(Alert);

使用方法:

外部插件内使用:
import Vue from 'vue';
const _ = new Vue();

_.$loading.show();
_.$loading.hide();


_.$alert({msg: '提示信息', type: "error"});




vue文件内使用:

this.$loading.show();
this.$loading.hide();

this.$alert({msg: '提示信息', type: "error"});

 

### Vue3 中封装 Axios 的示例及最佳实践 在 Vue3 项目中,通过合理封装 Axios 可以提升项目的可维护性和复用性。以下是基于提供的参考资料以及行业标准的最佳实践。 #### 一、创建 Axios 实例 为了统一管理 API 请求的基础配置,可以创建一个独立的 Axios 实例并设置默认值。这有助于减少重复代码量,并集中化配置管理[^1]。 ```javascript // utils/request.js import axios from 'axios'; const service = axios.create({ baseURL: process.env.VUE_APP_BASE_API, // 设置基础 URL 地址 timeout: 5000, // 超时时间 (毫秒) }); export default service; ``` #### 二、添加请求拦截器 请求拦截器允许我们在请求发送之前对其进行预处理,比如添加认证令牌或修改请求头等操作[^3]。 ```javascript service.interceptors.request.use( config => { const token = localStorage.getItem('token'); // 假设存储的是 JWT Token if (token) { config.headers['Authorization'] = `Bearer ${token}`; } return config; }, error => Promise.reject(error) ); ``` #### 三、添加响应拦截器 响应拦截器能够帮助我们统一对服务器返回的数据进行解析或者错误提示逻辑。 ```javascript service.interceptors.response.use( response => { const res = response.data; if (res.code !== 200) { // 自定义状态码判断失败情况 console.error(`Error Code: ${res.code}, Message: ${res.message}`); return Promise.reject(new Error(res.message || 'Request failed')); } else { return res; // 返回成功的数据部分 } }, error => { console.error("Network Error", error); // 处理网络异常或其他问题 return Promise.reject(error); } ); ``` #### 四、封装通用请求方法 将 Axios 封装成更简洁易用的形式,便于后续调用。 ```javascript // api/index.js import service from '@/utils/request'; export function fetchList(params) { return service.get('/list', { params }); } export function addItem(data) { return service.post('/add', data); } ``` #### 五、在 Vue 组件中的使用方式 当完成以上封装之后,在任何 Vue 组件里都可以轻松发起 HTTP 请求而无需关心底层细节[^2]。 ```javascript <template> <div>{{ result }}</div> </template> <script setup> import { ref } from 'vue'; import { fetchList } from '@/api/index'; const result = ref(null); fetchList({ page: 1 }).then(response => { result.value = response.items; }).catch(err => { alert(err.message); }); </script> ``` #### 六、高级功能扩展 除了基本的功能外还可以考虑加入更多实用特性来增强用户体验和开发效率: - **文件上传支持**:针对图片或者其他多媒体资源提供专门的服务端接口适配方案。 - **全局 Loading 效果控制**:利用 Vuex 或 Pinia 来跟踪当前是否有正在进行中的异步任务从而显示加载动画。 - **动态切换 BaseURL**:根据不同环境变量自动调整目标主机地址。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

The৲One

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值