• 自己封装一个简易的toast提示组件


    以下是仿照nutui的toast组件进行封装的:

    文件结构:(在components下)

     index.js:

    import cusToast from './_toast';
    import './toast.scss';
    
    cusToast.install = function (Vue) {
        Vue.prototype['$cusToast'] = cusToast;
    }
    
    export default cusToast;
    _toast.js
    import Vue from "vue";
    import settings from "./toast.vue";
    
    let ToastConstructor = Vue.extend(settings);
    let instance;//实例
    let instanceArr = [];//实例列表
    let defaultOptionsMap = {};//默认配置参数地图
    const defaultOptions = {//默认配置参数
        msg:"",//提示文字
        type:"",//提示框类型
        visible:false,//是否显示
        duration: 2000, //显示时间(毫秒)
        timer: null,//计时器
        textTimer: null,//文本的计时器
        onClose: null,//关闭提示框回调
        closeOnClickOverlay: false,//是否可以点击遮罩来关闭提示框
        textAlignCenter: true,//文字是否居中
        bgColor: "#ffffff",//背景颜色
        coverColor: "rgba(0, 0, 0, 0.3)",//遮罩颜色
        customClass: "",//自定义类名
        msgColor:"#686f80",//提示文字颜色
    };
    
    let currentOptions = {
        //浅克隆一个默认配置
        ...defaultOptions
    };
    
    function _showToast() {
        //挂载组件
        instance.vm = instance.$mount();
        document.body.appendChild(instance.$el);
        Vue.nextTick(() => {
            instance.visible = true;
        });
    }
    
    function _getInstance(obj) {
        //获取组件实例
        let opt = {
            id: new Date().getTime(),//new Date().getTime()  避免重复出现弹出框
            ...currentOptions,//默认配置
            ...defaultOptionsMap[obj.type],//???
            ...obj,//传入的配置
        };
        //有相同id者共用一个实例,否则新增实例
        if (opt["id"] && instanceArr[opt["id"]]) {
            instance = instanceArr[opt["id"]];
            instance.hide(true);
            instance = Object.assign(instance, opt);
          } else {
            instance = new ToastConstructor({
                data: Object.assign(opt, obj)
            });
            opt["id"] && (instanceArr[opt["id"]] = instance);
        }
        _showToast();
        return instance;
    }
    
    function errorMsg(msg) {
        if (!msg) {
          console.warn(" msg不能为空");
          return;
        }
    }
    
    let Toast = {
        text(msg, obj = {}) {
            errorMsg(msg);
            return _getInstance({ ...obj, msg, type: "text" });
        },
        loading(msg, obj = {}){
            obj = { ...obj, id: obj.id || "loading", msg, type: "loading" };
            obj.duration = 0; //loading类型默认不自动关闭
            return _getInstance(obj);
        }
    };
    
    export default  Toast;

    toast.vue

    <template>
        <transition name="toastfade">
            <div 
                :id="id"
                :class="toastClass"
                v-if="visible"
                :style="{
                    'background-color': coverColor
                }"
                @click="clickCover">
                <div
                    class="cus-toast-inner"
                    :style="{
                        'text-align': textAlignCenter ? 'center' : 'left',
                        'background-color': type != 'loading' ? bgColor :''
                    }">
                    <div 
                        v-if="type != 'loading'"
                        class="cus-toast-text" 
                        :style="{
                            'color':msgColor
                        }">{{msg}}</div>
                    <div class="cus_confirm_btn" v-if="type != 'loading'" @click="closeToast">确认</div>
                    <div class="cus_loading" v-else>
                        <i class="cus-toast-icon-rotate"></i>
                        <div>{{msg}}</div>
                    </div>
                </div>
            </div>
        </transition>
    </template>
    
    <script>
    export default {
        watch: {
            visible(val) {
                if (val) {
                    this.show();
                }
            }
        },
        computed: {
            toastClass(){
                return [
                    "cus_toast",
                    this.customClass,
                ]
            },
        },
        data(){
            return{
                id:"",
                msg:"",
                type:"",
                visible:false,
                duration:2000,
                timer: null,//计时器
                textTimer: null,//文本的计时器
                onClose: null,//关闭提示框回调
                closeOnClickOverlay: false,//是否可以点击遮罩来关闭提示框
                textAlignCenter: true,//文字是否居中
                bgColor: "#ffffff",//背景颜色
                coverColor: "rgba(0, 0, 0, 0.3)",//遮罩颜色
                customClass: "",//自定义类名
                msgColor:"#686f80",//提示文字颜色
            }
        },
        methods: {
            show(force) {
                //显示
                this.clearTimer();
                clearTimeout(this.textTimer);
                if (this.duration) {
                    this.timer = setTimeout(() => {
                        this.hide(force);
                    }, this.duration);
                }
            },
            hide(force) {
                //隐藏
                this.clearTimer();//清除计时器
                this.visible = false;
                if (force) {
                    //清除文字计时器
                    clearTimeout(this.textTimer);
                } else {
                    //清除文字计时器  带提示语一起清空
                    this.textTimer = setTimeout(() => {
                        clearTimeout(this.textTimer);
                        this.msg = "";
                    }, 300);
                }
                typeof this.onClose === "function" && this.onClose();
            },
            clearTimer() {
                //清除计时器
                if (this.timer) {
                    clearTimeout(this.timer);
                    this.timer = null;
                }
            },
            clickCover() {
                //点击遮罩 关闭提示框
                if (this.closeOnClickOverlay) {
                    this.hide();
                }
            },
            closeToast(){
                //关闭弹窗
                this.hide();
            }
        },
        destroyed() {
            this.textTimer = null;
            this.timer = null;
        }
    }
    </script>

    toast.scss

    .cus_toast{
        position: fixed;
        left:0;
        top:0;
        bottom:0;
        right:0;
        height:100vh;
        text-align: center;
        box-sizing: border-box;
        // pointer-events: none;
        z-index: 9999;
        .cus-toast-inner {
            position: absolute;
            top:50%;
            left:50%;
            transform: translate(-50%,-50%);
            font-size: 14px;
            max-width: 65%;
            min-width:180px;
            text-align: center;
            line-height: 1.5;
            word-break: break-all;
            border-radius: 7px;
            color: #fff;
            overflow: hidden;
            .cus-toast-text{
                font-weight: bold;
                padding: 20px 10px 10px;
            }
            .cus_confirm_btn{
                height:40px;
                color:#136be0;
                line-height: 40px;
                border-top:1px solid  #ededed;
            }
            .cus_loading{
                color:#136be0;
                .cus-toast-icon-rotate {
                    display: inline-block;
                    width: 30px;
                    height: 30px;
                    background-repeat: no-repeat;
                    background-size: 100%;
                    animation: rotation 2s linear infinite;
                    background: url("data:image/svg+xml, %3Csvg class='icon' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='rgb(12,110,228)' d='M874.667 533.333h-192c-12.8 0-21.334-8.533-21.334-21.333 0-12.8 8.534-21.333 21.334-21.333h192c12.8 0 21.333 8.533 21.333 21.333 0 12.8-8.533 21.333-21.333 21.333zM648.533 407.467C640 416 627.2 416 618.667 407.467c-8.534-8.534-8.534-21.334 0-29.867L755.2 241.067c8.533-8.534 21.333-8.534 29.867 0 8.533 8.533 8.533 21.333 0 29.866L648.533 407.467zM512 896c-12.8 0-21.333-8.533-21.333-21.333v-192c0-12.8 8.533-21.334 21.333-21.334s21.333 8.534 21.333 21.334v192c0 12.8-8.533 21.333-21.333 21.333zm0-533.333c-12.8 0-21.333-8.534-21.333-21.334v-192c0-12.8 8.533-21.333 21.333-21.333s21.333 8.533 21.333 21.333v192c0 12.8-8.533 21.334-21.333 21.334zM270.933 782.933c-8.533 8.534-21.333 8.534-29.866 0s-8.534-21.333 0-29.866L377.6 616.533c8.533-8.533 21.333-8.533 29.867 0 8.533 8.534 8.533 21.334 0 29.867L270.933 782.933zm104.534-375.466L238.933 270.933c-8.533-8.533-8.533-21.333 0-29.866s21.334-8.534 29.867 0L405.333 377.6c8.534 8.533 8.534 21.333 0 29.867-6.4 6.4-21.333 6.4-29.866 0zM362.667 512c0 12.8-8.534 21.333-21.334 21.333h-192C136.533 533.333 128 524.8 128 512c0-12.8 8.533-21.333 21.333-21.333h192c12.8 0 21.334 8.533 21.334 21.333zm285.866 104.533l136.534 136.534c8.533 8.533 8.533 21.333 0 29.866-8.534 8.534-21.334 8.534-29.867 0L618.667 646.4c-8.534-8.533-8.534-21.333 0-29.867 6.4-6.4 21.333-6.4 29.866 0z'/%3E%3C/svg%3E") no-repeat;
                    background-size: cover;
                }
            }
                
        }
        
    }
    
    
    
    //渐变
    .toastfade-enter-active {
        transition: opacity 0.1s;
    }
    
    .toastfade-leave-active {
        transition: opacity 0.3s;
    }
    
    .toastfade-enter,
    .toastfade-leave-active {
        opacity: 0;
    }

    使用

    在main.js中注册

    import cusToast from '@/components/cusToast';
    cusToast.install(Vue);

    在页面中使用

    this.$toast.text("提示语",3000)

    loading的使用

     import cusToast from '@/components/cusToast';
    
    var loading;
    
    loading=cusToast.loading('');//开启loading
    
    loading.hide();//关闭loading

    可以根据自己的要求调整

  • 相关阅读:
    全球覆盖 哈希
    陌上花开 模板 三维偏序
    洛谷 P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并
    熟练剖分(tree) 树形DP
    那一天她离我而去 二进制分组建图
    平凡的函数 线性筛积性函数
    wmz的数数(数状数组)
    跳一跳 概率与期望
    洛谷 P4284 [SHOI2014]概率充电器 概率与期望+换根DP
    SpringBoot手动事务参考链接
  • 原文地址:https://www.cnblogs.com/fqh123/p/13124778.html
Copyright © 2020-2023  润新知