用vue完成模态框组件

基础上每一个项目都须要用到模态框组件,因为在近来的项目中,alert组件和confirm是两套完整不一样的设想,所以我将他们分成了两个组件,本文重要议论的是confirm组件的完成。

组件构造

<template>
    <div class="modal" v-show="show" transition="fade">
        <div class="modal-dialog">
            <div class="modal-content">
                <!--头部-->
                <div class="modal-header">
                    <slot name="header">
                        <p class="title">{{modal.title}}</p>
                    </slot>
                    <a v-touch:tap="close(0)" class="close" href="javascript:void(0)"></a>
                </div>
                <!--内容地区-->
                <div class="modal-body">
                    <slot name="body">
                        <p class="notice">{{modal.text}}</p>
                    </slot>
                </div>
                <!--尾部,操纵按钮-->
                <div class="modal-footer">
                    <slot name="button">
                        <a v-if="modal.showCancelButton" href="javascript:void(0)" class="button {{modal.cancelButtonClass}}" v-touch:tap="close(1)">{{modal.cancelButtonText}}</a>
                        <a v-if="modal.showConfirmButton" href="javascript:void(0)" class="button {{modal.confirmButtonClass}}" v-touch:tap="submit">{{modal.confirmButtonText}}</a>
                    </slot>
                </div>
            </div>
        </div>
    </div>
    <div v-show="show" class="modal-backup" transition="fade"></div>
</template>  

模态框构造分为三部份,离别为头部、内部地区和操纵地区,都供应了slot,能够根据须要定制。

款式

.modal {
    position: fixed;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 1001;
    -webkit-overflow-scrolling: touch;
    outline: 0;
    overflow: scroll;
    margin: 30/@rate auto;
}
.modal-dialog {
    position: absolute;
    left: 50%;
    top: 0;
    transform: translate(-50%,0);
    width: 690/@rate;
    padding: 50/@rate 40/@rate;
    background: #fff;
}
.modal-backup {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 1000;
    background: rgba(0, 0, 0, 0.5);
}

这里只是一些基础款式,没什么好说的,此次项目是在挪动端,用了淘宝的自适应规划计划,@rate是切稿时刻的转换率。

接口定义

/**
 * modal 模态接口参数
 * @param {string} modal.title 模态框题目
 * @param {string} modal.text 模态框内容
 * @param {boolean} modal.showCancelButton 是不是显现作废按钮
 * @param {string} modal.cancelButtonClass 作废按钮款式
 * @param {string} modal.cancelButtonText 作废按钮笔墨
 * @param {string} modal.showConfirmButton 是不是显现肯定按钮
 * @param {string} modal.confirmButtonClass 肯定按钮款式
 * @param {string} modal.confirmButtonText 肯定按钮标笔墨
 */
props: ['modalOptions'],
computed: {
    /**
     * 格式化props进来的参数,对参数给予默认值
     */
    modal: {
        get() {
            let modal = this.modalOptions;
            modal = {
                title: modal.title || '提醒',
                text: modal.text,
                showCancelButton: typeof modal.showCancelButton === 'undefined' ? true : modal.showCancelButton,
                cancelButtonClass: modal.cancelButtonClass ? modal.showCancelButton : 'btn-default',
                cancelButtonText: modal.cancelButtonText ? modal.cancelButtonText : '作废',
                showConfirmButton: typeof modal.showConfirmButton === 'undefined' ? true : modal.cancelButtonClass,
                confirmButtonClass: modal.confirmButtonClass ? modal.confirmButtonClass : 'btn-active',
                confirmButtonText: modal.confirmButtonText ? modal.confirmButtonText : '肯定',
            };
            return modal;
        },
    },
},

这里定义了接口的参数,能够自定义题目、内容、是不是显现按钮和按钮的款式,用一个computed来做参数默认值的掌握。

模态框内部要领

data() {
    return {
        show: false,   // 是不是显现模态框
        resolve: '',
        reject: '',
        promise: '',  // 保留promise对象
    };
},
methods: {
    /**
     * 肯定,将promise断定为完成态
     */
    submit() {
        this.resolve('submit');
    },
    /**
     * 封闭,将promise断定为reject状况
     * @param type {number} 封闭的体式格局 0示意封闭按钮封闭,1示意作废按钮封闭
     */
    close(type) {
        this.show = false;
        this.reject(type);
    },
    /**
     * 显现confirm弹出,并建立promise对象
     * @returns {Promise}
     */
    confirm() {
        this.show = true;
        this.promise = new Promise((resolve, reject) => {
            this.resolve = resolve;
            this.reject = reject;
        });
        return this.promise;   //返回promise对象,给父级组件挪用
    },
},

在模态框内部定义了三个要领,最中心部份confirm要领,这是一个定义在模态框内部,然则是给运用模态框的父级组件挪用的要领,该要领返回的是一个promise对象,并将resolve和reject存放于modal组件的data中,点击作废按钮时,断定为reject状况,并将模态框封闭掉,点肯定按钮时,断定为resolve状况,模态框没有封闭,由挪用modal组件的父级组件的回调解理完成后手动掌握封闭模态框。

挪用

<!-- template -->
<confirm v-ref:dialog :modal-options.sync="modal"></confirm>
<!-- methods -->
this.$refs.dialog.confirm().then(() => {
    // 点击肯定按钮的回调解理
    callback();
    this.$refs.dialog.show = false; 
}).catch(() => {
    // 点击作废按钮的回调解理
    callback();
});

v-ref建立一个索引,就很轻易拿到模态框组件内部的要领了。如许一个模态框组件就完成了。

其他完成要领

在模态框组件中,比较难完成的应该是点击肯定和作废按钮时,父级的回调解理,我在做这个组件时,也参考了一些实在完成计划。

运用事宜转发

这个要领是我的同事完成的,用在上一个项目,采纳的是$dispatch和$broadcast来派发或播送事宜。

首先在根组件吸收dispatch过来的transmit事宜,再将transmit事宜通报过来的eventName播送下去

events: {
    /**
     * 转发事宜
     * @param  {string} eventName 事宜称号
     * @param  {object} arg       事宜参数
     * @return {null}
     */
    'transmit': function (eventName, arg) {
        this.$broadcast(eventName, arg);
    }
},

其次是模态框组件内部吸收从父级组件通报过来的肯定和作废按钮所触发的事宜名,点击作废和肯定按钮的时刻触发

// 吸收事宜,取得须要作废和肯定按钮的事宜名
events: {
    'tip': function(obj) {
        this.events = {
            cancel: obj.events.cancel,
            confirm: obj.events.confirm
        }
    }
}
// 作废按钮
cancel:function() {
    this.$dispatch('transmit',this.events.cancel);
}
// 肯定按钮
submit: function() {
    this.$dispatch('transmit',this.events.submit);
}

在父级组件中挪用模态框以下:

this.$dispatch('transmit','tip',{
    events: {
        confirm: 'confirmEvent'
    }
});
this.$once('confirmEvent',function() {
    callback();
}

先是通报tip事宜,将事宜名通报给模态框,再用$once监听肯定或作废按钮所触发的事宜,事宜触发后举行回调。

这类要领看起来是不是是很晕?所以vue 2.0作废了$dispatch和$broadcast,我们在近来的项目中虽然还在用1.0,然则也不再用$dispatch和$broadcast,轻易今后的晋级。

运用emit来触发

这类要领来自vue-bootstrap-modal,点击作废和肯定按钮的时刻离别emit一个事宜,直接在组件上监听这个事宜,这类做法的优点是事宜比较轻易追踪。

// 肯定按钮
ok () {
    this.$emit('ok');
    if (this.closeWhenOK) {
        this.show = false;
    }
},
// 作废按钮
cancel () {
    this.$emit('cancel');
    this.show = false;
},

挪用:

<modal title="Modal Title" :show.sync="show" @ok="ok" @cancel="cancel">
    Modal Text
</modal>

然则我们在运用的时刻常常会碰到如许的场景,在一个组件的内部,常常会用到多个对话框,对话框能够只是笔墨有点区分,回调差别,这时候就须要在template中为每一个对话框都写一次<modal></modal>,有点贫苦。不想每次写,能够用v-for来遍历,这篇文章关于 vue 弹窗组件的一些感受有我与作者的议论,能够参考一下。

参考资料

按例放张民众号的二维码,迎接关注:

《用vue完成模态框组件》

    原文作者:对角另一面
    原文地址: https://segmentfault.com/a/1190000006971054
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞