modal.js


Vue.component("cc-modal", {
    props: {
        value: {
            type: Boolean,
            default: false
        },
        title: {
            type: String,
            default: "Modal"
        },
        width: {
            default: "50%"
        },
        showFooter: {
            type: Boolean,
            default: true
        },
        footerAlign: {
            type: String,
            default: "right"
        },
        dragable: {
            type: Boolean,
            default: false
        },
        closeOnEsc: {
            type: Boolean,
            default: false
        },
        okLoading: {
            type: Boolean,
            default: false
        },
        customClose: {
            type: Boolean,
            default: false
        }
    },
    template: '\
    <div>\
        <transition name="fade">\
            <div v-if="visible" class="cc-modal-masklayer" :style="modalLayerStyle"></div>\
        </transition>\
        <transition name="fade-down">\
            <div class="cc-modal-container" v-if="visible" :style="modalLayerStyle">\
                <div class="cc-modal-content" :style="modalStyle" ref="modalContent">\
                    <div class="cc-modal-header" :style="dragCursor" @mousedown="dragModal">\
                        <slot name="header">\
                            <span class="cc-modal-title">{{title}}</span>\
                        </slot>\
                        <span class="cc-modal-close" @click="close">×</span>\
                    </div>\
                    <div class="cc-modal-body">\
                        <slot></slot>\
                    </div>\
                    <div class="cc-modal-footer" v-if="showFooter" :style="modalFooterAlign">\
                        <slot name="footer">\
                            <cc-button @click="cancel">取消</cc-button>\
                            <cc-button classType="success" @click="ok" :loading="loading">确定</cc-button>\
                        </slot>\
                    </div>\
                </div>\
            </div>\
        </transition>\
    </div>\
    ',
    // 这里依赖extend.js中的绑定事件方法
    mounted: function () {
        this.$parent.modalCount = this.$parent.modalCount ? this.$parent.modalCount + 1 : 1;
        if (this.closeOnEsc) {
            this.Fn.addEventHandler(document, "keyup", this.escClose);
        }
    },
    beforeDestroy: function () {
        if (this.closeOnEsc) {
            this.Fn.removeEventHandler(document, "keyup", this.escClose);
        }
    },
    data: function () {
        return {
            visible: false,
            loading: false
        }
    },
    computed: {
        modalStyle: function () {
            var obj = {
                width: this.width,
                left: 0,
                top: "100px"
            };
            var width = this.width,
                windowWidth = this.Fn.getInnerClient().width;
            if (!!Number(this.width)) {
                obj.width = width + "px";
                obj.left = ((windowWidth - width) / 2) + "px";
            } else {
                if (width.indexOf("%") > -1) {
                    obj.left = (windowWidth * (1 - Number(width.replace("%", "")) / 100) / 2) + "px";
                } else if (width.indexOf("px") > -1) {
                    obj.left = (windowWidth - Number(width.replace("px", ""))) / 2 + "px";
                }
            }
            return obj
        },
        modalLayerStyle: function () {
            return {
                "z-index": 9999 + this.$parent.modalCount
            }
        },
        modalFooterAlign: function () {
            return {
                "text-align": this.footerAlign
            }
        },
        dragCursor: function () {
            if (this.dragable) return {
                cursor: "move"
            }
            return null
        }
    },
    methods: {
        close: function () {
            this.visible = false;
            this.$emit('input', false);
        },
        ok: function (event) {
            this.$emit("ok", event);
            if (!this.customClose && !this.okLoading) {
                this.close()
            } else {
                if (this.okLoading) {
                    this.loading = true
                }
            }
        },
        cancel: function (event) {
            this.$emit("cancel", event);
            if (!this.customClose) {
                this.close()
            }
        },
        escClose: function (event) {
            if (this.visible && event.keyCode === 27) {
                this.close()
            }
        },
        dragModal: function (eve) {
            if (this.dragable) {
                var self = this,
                    isDraging = true,
                    modalContent = this.$refs.modalContent,
                    rect = modalContent.getBoundingClientRect(),
                    w = rect.width,
                    h = rect.height,
                    ol = rect.left,
                    ot = rect.top,
                    pointX = eve.clientX,
                    pointY = eve.clientY,
                    maxW = this.Fn.getInnerClient().width - w,
                    maxH = this.Fn.getInnerClient().height - h;
                this.Fn.addEventHandler(document, "mousemove", function (e) {
                    if (isDraging) {
                        window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
                        var left = e.clientX - pointX + ol,
                            top = e.clientY - pointY + ot;
                        if (left < 0) left = 0;
                        if (left > maxW) left = maxW;
                        if (top < 0) top = 0;
                        if (top > maxH) top = maxH;
                        modalContent.style.left = left + "px";
                        modalContent.style.top = top + "px";
                    }
                });
                this.Fn.addEventHandler(document, "mouseup", function (e) {
                    isDraging = false;
                    self.Fn.removeEventHandler(document, "mousemove");
                });
            }
        }
    },
    watch: {
        value: function (val) {
            this.visible = val
            if (!val) {
                this.loading = false
            }
        },
        okLoading: function (val) {
            if (!val) {
                this.loading = false
            }
        }
    }
});


// 通过JS调用
var ccModal = function (props) {
    if (ccModal.modal) return;
    var _props = props || {};
    var instance = new Vue({
        data: {
            template: _props.template,
            title: _props.title,
            width: _props.width,
            okFn: _props.okFn,
            cancelFn: _props.cancelFn,
            okLoading: _props.okLoading,
            dragable: _props.dragable,
            showFooter: _props.showFooter,
            footerAlign: _props.footerAlign,
            closeOnEsc: _props.closeOnEsc,
            confirmType: _props.confirmType,
            customButtons: _props.customButtons,
            customButtonsLoading: {}
        },
        template: '\
            <cc-modal :title="title" :width="width" @ok="ok" @cancel="cancel" :ok-loading="okLoading" :dragable="dragable" :show-footer="showFooter" :footer-align="footerAlign" :close-on-esc="closeOnEsc" :custom-close="customClose">\
                <div v-if="confirmType" class="confirmModal">\
                    <i class="fa fa-exclamation-circle" :style="confirmTypeColor" aria-hidden="true"></i>\
                    {{computedTemplate}}\
                </div>\
                <div v-else="confirmType">{{computedTemplate}}</div>\
                <div v-if="!!customButtons" slot="footer">\
                    <cc-button v-for="(item,index) in customButtons" :key="item.mark" @click="customButtonClick(item,index)" :loading="customButtonsLoading[item.mark]" :class-type="item.classType">{{item.text}}</cc-button>\
                </div>\
            </cc-modal>\
        ',
        computed: {
            customClose: function () {
                if (this.okFn || this.cancelFn) {
                    return true
                }
                return false
            },
            confirmTypeColor: function () {
                var color;
                switch (this.confirmType) {
                    case 1:
                        color = "#00cc99"
                        break
                    case 2:
                        color = "#00ccff"
                        break
                    case 3:
                        color = "#eeaa00"
                        break
                    case 4:
                        color = "#ee6666"
                        break
                };
                return {
                    color: color
                }
            },
            computedTemplate: function () {
                // if (typeof this.template != "string") {
                //     throw new Error("template必填且必须是String类型!")
                // }
                // if (this.template.length == this.template.indexOf(".html") + 5) {
                //     console.log("URL模板")
                // } else if (this.template.indexOf("#") == 0) {
                //     console.log("ID模板")
                //     var element = document.getElementById(this.template.substr(1));
                //     return element
                // } else if (this.template.indexOf("<") == 0 && this.template.indexOf(">") == this.template.length - 1) {
                //     console.log("HTML模板")
                // }else{
                //     console.log("String模板")
                // }
                console.log("太复杂了,能力有限暂时做不出来,所以还是JS调用弹框的时候template不做解析,因此只应用于类似于confirm之类的弹框,更复杂的用HTML的形式去调用吧!\n贴一个参考网址,以后有兴趣了再深究:https://segmentfault.com/a/1190000010611308");
                // return Vue.compile(this.template)
                return this.template
            }
        },
        methods: {
            cancel: function () {
                if (this.cancelFn) {
                    this.cancelFn()
                } else {
                    this.$children[0].visible = false;
                    this.remove();
                }
            },
            ok: function () {
                if (this.okFn) {
                    this.okFn()
                } else {
                    if (!this.okLoading) {
                        this.okLoading = false;
                        this.$children[0].visible = false;
                    }
                }
            },
            customButtonClick: function (item, index) {
                if (item.loading) {
                    this.$set(this.customButtonsLoading, item.mark, true)
                }
                if (item.fn && typeof item.fn == "function") {
                    item.fn()
                }
            },
            remove: function () {
                var self = this;
                setTimeout(function () {
                    self.destroy();
                }, 300);
            },
            destroy: function () {
                this.$destroy();
                document.body.removeChild(this.$el);
            }
        }
    });
    document.body.appendChild(instance.$mount().$el);
    // 设置弹窗默认打开
    instance.$children[0].visible = true;
    return {
        modal: instance.$children[0],
        open: function () {
            ccModal.modal.visible = true;
        },
        close: function () {
            ccModal.modal.visible = false;
            ccModal.modal.$parent.okLoading = false;
            ccModal.modal.$parent.customButtonsLoading = {};
        },
        remove: function () {
            ccModal.close();
            ccModal.modal.$parent.remove();
        }
    }
};

ccModal.confirm = function (props) {
    var _props = props || {}, type;
    switch (_props.type) {
        case "success":
            type = 1
            break
        case "info":
            type = 2
            break
        case "warn":
            type = 3
            break
        case "error":
            type = 4
            break
    };
    ccModal({
        width: props.width || "360px",
        title: props.title || "确认",
        template: props.message,
        okFn: _props.okFn,
        cancelFn: _props.cancelFn,
        okLoading: _props.okLoading,
        dragable: _props.dragable,
        showFooter: _props.showFooter,
        footerAlign: _props.footerAlign,
        closeOnEsc: _props.closeOnEsc,
        confirmType: type,
        customButtons: _props.customButtons
    });
};








 

转载于:https://my.oschina.net/u/3288561/blog/1558259

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值