资讯专栏INFORMATION COLUMN

用vue实现模态框组件

mrcode / 2409人阅读

摘要:组件结构头部内容区域尾部操作按钮模态框结构分为三部分,分别为头部内部区域和操作区域,都提供了,可以根据需要定制。调用点击确定按钮的回调处理点击取消按钮的回调处理用创建一个索引就很方便拿到模态框组件内部的方法了。

基本上每个项目都需要用到模态框组件,由于在最近的项目中,alert组件和confirm是两套完全不一样的设计,所以我将他们分成了两个组件,本文主要讨论的是confirm组件的实现。

组件结构
  

模态框结构分为三部分,分别为头部、内部区域和操作区域,都提供了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组件的父级组件的回调处理完成后手动控制关闭模态框。

调用



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 Text

但是我们在使用的时候经常会遇到这样的场景,在一个组件的内部,经常会用到多个对话框,对话框可能只是文字有点区别,回调不同,这时就需要在template中为每个对话框都写一次,有点麻烦。不想每次写,可以用v-for来遍历,这篇文章关于 vue 弹窗组件的一些感想有我与作者的讨论,可以参考一下。

参考资料

vue.js dynamic create nest modal

es6 Promise对象

vue-bootstrap-modal

关于 vue 弹窗组件的一些感想

照例放张公众号的二维码,欢迎关注:

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/87916.html

相关文章

  • vue的生命周期解析并通过表单理解MVVM(不仅理论,图文并茂)

    摘要:在前端页面中,把用纯对象表示,负责显示,两者做到了最大限度的分离。的显示与否和的布尔值有关,还是只关注数据的变化。两个组件的布尔值通过两个临近的按钮控制,初始值和的结果都是。组件的声明在组件上,则完全没有进入生命周期。 开始前说一说 吐槽 首先, 文章有谬误的地方, 请评论, 我会进行验证修改。谢谢。 vue真是个好东西,但vue的中文文档还有很大的改进空间,有点大杂烩的意思,对于怎么...

    silvertheo 评论0 收藏0
  • vue的生命周期解析并通过表单理解MVVM(不仅理论,图文并茂)

    摘要:在前端页面中,把用纯对象表示,负责显示,两者做到了最大限度的分离。的显示与否和的布尔值有关,还是只关注数据的变化。两个组件的布尔值通过两个临近的按钮控制,初始值和的结果都是。组件的声明在组件上,则完全没有进入生命周期。 开始前说一说 吐槽 首先, 文章有谬误的地方, 请评论, 我会进行验证修改。谢谢。 vue真是个好东西,但vue的中文文档还有很大的改进空间,有点大杂烩的意思,对于怎么...

    lijy91 评论0 收藏0
  • vue中props的双向绑定

    摘要:在的学习中,一开始我是自己写组件练手的,在这个过程中我遇到一个问题父组件传递给子组件参数直接在子组件里直接使用是可以实时更新的如果在,等声明或者直接赋值给的时候,再用的时候是不可以实时更新的内部的是可以实时更新的但是内部不可以强制去改变父元 在vue的学习中,一开始我是自己写组件练手的,在这个过程中我遇到一个问题:props:父组件传递给子组件参数(1)props直接在子组件里直接使用...

    Amos 评论0 收藏0
  • vue中props的双向绑定

    摘要:在的学习中,一开始我是自己写组件练手的,在这个过程中我遇到一个问题父组件传递给子组件参数直接在子组件里直接使用是可以实时更新的如果在,等声明或者直接赋值给的时候,再用的时候是不可以实时更新的内部的是可以实时更新的但是内部不可以强制去改变父元 在vue的学习中,一开始我是自己写组件练手的,在这个过程中我遇到一个问题:props:父组件传递给子组件参数(1)props直接在子组件里直接使用...

    vvpale 评论0 收藏0
  • vue中props的双向绑定

    摘要:在的学习中,一开始我是自己写组件练手的,在这个过程中我遇到一个问题父组件传递给子组件参数直接在子组件里直接使用是可以实时更新的如果在,等声明或者直接赋值给的时候,再用的时候是不可以实时更新的内部的是可以实时更新的但是内部不可以强制去改变父元 在vue的学习中,一开始我是自己写组件练手的,在这个过程中我遇到一个问题:props:父组件传递给子组件参数(1)props直接在子组件里直接使用...

    douzifly 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<