如何用vue实现模态框组件

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

组件结构


  1. <template> 
  2.     <div class="modal" v-show="show" transition="fade"> 
  3.         <div class="modal-dialog"> 
  4.             <div class="modal-content"> 
  5.                 <!--头部--> 
  6.                 <div class="modal-header"> 
  7.                     <slot name="header"> 
  8.                         <p class="title">{{modal.title}}</p> 
  9.                     </slot> 
  10.                     <a v-touch:tap="close(0)" class="close" href="javascript:void(0)"></a> 
  11.                 </div> 
  12.                 <!--内容区域--> 
  13.                 <div class="modal-body"> 
  14.                     <slot name="body"> 
  15.                         <p class="notice">{{modal.text}}</p> 
  16.                     </slot> 
  17.                 </div> 
  18.                 <!--尾部,操作按钮--> 
  19.                 <div class="modal-footer"> 
  20.                     <slot name="button"> 
  21.                         <a v-if="modal.showCancelButton" href="javascript:void(0)" class="button {{modal.cancelButtonClass}}" v-touch:tap="close(1)">{{modal.cancelButtonText}}</a> 
  22.                         <a v-if="modal.showConfirmButton" href="javascript:void(0)" class="button {{modal.confirmButtonClass}}" v-touch:tap="submit">{{modal.confirmButtonText}}</a> 
  23.                     </slot> 
  24.                 </div> 
  25.             </div> 
  26.         </div> 
  27.     </div> 
  28.     <div v-show="show" class="modal-backup" transition="fade"></div> 
  29. </template>   

模态框结构分为三部分,分别为头部、内部区域和操作区域,都提供了slot,可以根据需要定制。

样式


  1. .modal { 
  2.     position: fixed; 
  3.     left: 0; 
  4.     top: 0; 
  5.     right: 0; 
  6.     bottom: 0; 
  7.     z-index: 1001; 
  8.     -webkit-overflow-scrolling: touch; 
  9.     outline: 0; 
  10.     overflow: scroll; 
  11.     margin: 30/@rate auto; 
  12. .modal-dialog { 
  13.     position: absolute; 
  14.     left: 50%; 
  15.     top: 0; 
  16.     transform: translate(-50%,0); 
  17.     width: 690/@rate; 
  18.     padding: 50/@rate 40/@rate; 
  19.     background: #fff; 
  20. .modal-backup { 
  21.     position: fixed; 
  22.     top: 0; 
  23.     right: 0; 
  24.     bottom: 0; 
  25.     left: 0; 
  26.     z-index: 1000; 
  27.     background: rgba(0, 0, 0, 0.5); 
  28. }  

这里只是一些基本样式,没什么好说的,这次项目是在移动端,用了淘宝的自适应布局方案,@rate是切稿时候的转换率。

接口定义


  1. /** 
  2.  * modal 模态接口参数 
  3.  * @param {string} modal.title 模态框标题 
  4.  * @param {string} modal.text 模态框内容 
  5.  * @param {boolean} modal.showCancelButton 是否显示取消按钮 
  6.  * @param {string} modal.cancelButtonClass 取消按钮样式 
  7.  * @param {string} modal.cancelButtonText 取消按钮文字 
  8.  * @param {string} modal.showConfirmButton 是否显示确定按钮 
  9.  * @param {string} modal.confirmButtonClass 确定按钮样式 
  10.  * @param {string} modal.confirmButtonText 确定按钮标文字 
  11.  */ 
  12. props: ['modalOptions'], 
  13. computed: { 
  14.     /** 
  15.      * 格式化props进来的参数,对参数赋予默认值 
  16.      */ 
  17.     modal: { 
  18.         get() { 
  19.             let modal = this.modalOptions; 
  20.             modal = { 
  21.                 title: modal.title || '提示', 
  22.                 text: modal.text, 
  23.                 showCancelButton: typeof modal.showCancelButton === 'undefined' ? true : modal.showCancelButton, 
  24.                 cancelButtonClass: modal.cancelButtonClass ? modal.showCancelButton : 'btn-default', 
  25.                 cancelButtonText: modal.cancelButtonText ? modal.cancelButtonText : '取消', 
  26.                 showConfirmButton: typeof modal.showConfirmButton === 'undefined' ? true : modal.cancelButtonClass, 
  27.                 confirmButtonClass: modal.confirmButtonClass ? modal.confirmButtonClass : 'btn-active', 
  28.                 confirmButtonText: modal.confirmButtonText ? modal.confirmButtonText : '确定', 
  29.             }; 
  30.             return modal; 
  31.         }, 
  32.     }, 
  33. },  

这里定义了接口的参数,可以自定义标题、内容、是否显示按钮和按钮的样式,用一个computed来做参数默认值的控制。

模态框内部方法


  1. data() { 
  2.     return { 
  3.         show: false,   // 是否显示模态框 
  4.         resolve: '', 
  5.         reject: '', 
  6.         promise: '',  // 保存promise对象 
  7.     }; 
  8. }, 
  9. methods: { 
  10.     /** 
  11.      * 确定,将promise断定为完成态 
  12.      */ 
  13.     submit() { 
  14.         this.resolve('submit'); 
  15.     }, 
  16.     /** 
  17.      * 关闭,将promise断定为reject状态 
  18.      * @param type {number} 关闭的方式 0表示关闭按钮关闭,1表示取消按钮关闭 
  19.      */ 
  20.     close(type) { 
  21.         this.show = false; 
  22.         this.reject(type); 
  23.     }, 
  24.     /** 
  25.      * 显示confirm弹出,并创建promise对象 
  26.      * @returns {Promise} 
  27.      */ 
  28.     confirm() { 
  29.         this.show = true; 
  30.         this.promise = new Promise((resolve, reject) => { 
  31.             this.resolve = resolve; 
  32.             this.reject = reject; 
  33.         }); 
  34.         return this.promise;   //返回promise对象,给父级组件调用 
  35.     }, 
  36. },  

在模态框内部定义了三个方法,最核心部分confirm方法,这是一个定义在模态框内部,但是是给使用模态框的父级组件调用的方法,该方法返回的是一个promise对象,并将resolve和reject存放于modal组件的data中,点击取消按钮时,断定为reject状态,并将模态框关闭掉,点确定按钮时,断定为resolve状态,模态框没有关闭,由调用modal组件的父级组件的回调处理完成后手动控制关闭模态框。

调用


  1. <!-- template --> 
  2. <confirm v-ref:dialog :modal-options.sync="modal"></confirm> 
  3. <!-- methods --> 
  4. this.$refs.dialog.confirm().then(() => { 
  5.     // 点击确定按钮的回调处理 
  6.     callback(); 
  7.     this.$refs.dialog.show = false;  
  8. }).catch(() => { 
  9.     // 点击取消按钮的回调处理 
  10.     callback(); 
  11. });  

用v-ref创建一个索引,就很方便拿到模态框组件内部的方法了。这样一个模态框组件就完成了。

其他实现方法

在模态框组件中,比较难实现的应该是点击确定和取消按钮时,父级的回调处理,我在做这个组件时,也参考了一些其实实现方案。

使用事件转发

这个方法是我的同事实现的,用在上一个项目,采用的是$dispatch和$broadcast来派发或广播事件。

首先在根组件接收dispatch过来的transmit事件,再将transmit事件传递过来的eventName广播下去


  1. events: { 
  2.     /** 
  3.      * 转发事件 
  4.      * @param  {string} eventName 事件名称 
  5.      * @param  {object} arg       事件参数 
  6.      * @return {null} 
  7.      */ 
  8.     'transmit': function (eventName, arg) { 
  9.         this.$broadcast(eventName, arg); 
  10.     } 
  11. },  

其次是模态框组件内部接收从父级组件传递过来的确定和取消按钮所触发的事件名,点击取消和确定按钮的时候触发


  1. // 接收事件,获得需要取消和确定按钮的事件名 
  2. events: { 
  3.     'tip': function(obj) { 
  4.         this.events = { 
  5.             cancel: obj.events.cancel, 
  6.             confirm: obj.events.confirm 
  7.         } 
  8.     } 
  9. // 取消按钮 
  10. cancel:function() { 
  11.     this.$dispatch('transmit',this.events.cancel); 
  12. // 确定按钮 
  13. submit: function() { 
  14.     this.$dispatch('transmit',this.events.submit); 
  15. }  

在父级组件中调用模态框如下:


  1. this.$dispatch('transmit','tip',{ 
  2.     events: { 
  3.         confirm: 'confirmEvent' 
  4.     } 
  5. }); 
  6. this.$once('confirmEvent',function() { 
  7.     callback(); 
  8. }  

先是传递tip事件,将事件名传递给模态框,再用$once监听确定或取消按钮所触发的事件,事件触发后进行回调。

这种方法看起来是不是很晕?所以vue 2.0取消了$dispatch和$broadcast,我们在最近的项目中虽然还在用1.0,但是也不再用$dispatch和$broadcast,方便以后的升级。

使用emit来触发

这种方法来自vue-bootstrap-modal,点击取消和确定按钮的时候分别emit一个事件,直接在组件上监听这个事件,这种做法的好处是事件比较容易追踪。


  1. // 确定按钮 
  2. ok () { 
  3.     this.$emit('ok'); 
  4.     if (this.closeWhenOK) { 
  5.         this.show = false; 
  6.     } 
  7. }, 
  8. // 取消按钮 
  9. cancel () { 
  10.     this.$emit('cancel'); 
  11.     this.show = false; 
  12. },  

调用:


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

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

作者:对角另一面

来源:51CTO

时间: 2024-09-04 14:59:31

如何用vue实现模态框组件的相关文章

利用vue实现模态框组件_javascript技巧

基本上每个项目都需要用到模态框组件,由于在最近的项目中,alert组件和confirm是两套完全不一样的设计,所以我将他们分成了两个组件,本文主要讨论的是confirm组件的实现. 组件结构 <template> <div class="modal" v-show="show" transition="fade"> <div class="modal-dialog"> <div cla

Bootstrap每天必学之模态框(Modal)插件_javascript技巧

本节课我们主要学习一下 Bootstrap 中的模态框插件, 这是一款交互式网站非常常见的弹窗功能插件. 更多关于Bootstrap模态框插件内容请点击专题<Bootstrap Modal使用教程>进行学习,希望大家喜欢,下面继续 一.基本使用使用模态框的弹窗组件需要三层 div 容器元素,分别为 modal(模态声明层). dialog(窗口声明层).content(内容层).在内容层里面,还有三层,分别为 header(头部).body(主体).footer(注脚). //基本实例 <

转:如何用Visual C#做组件

如何用Visual C#做组件 用Visual C#来做组件,其实是一件很容易的事情.至少比用VISUAL C++要容易的多.在本文中,笔者将为您详细介绍如何来做一个组件.我们可以通过二个步骤来完成这个过程:1.制作一个组件:2.在客户端测试这个组件. 一.制作一个组件 1.首先建立一个新类库工程文件 选择File->New->Project->Visual C# Projects->Class Library.填入工程文件名称,并且通过Browse按钮选择文件要存放的目录.然后点

如何用Visual C#做组件

visual   如何用Visual C#做组件 用Visual C#来做组件,其实是一件很容易的事情.至少比用VISUAL C++要容易的多.在本文中,笔者将为您详细介绍如何来做一个组件.我们可以通过二个步骤来完成这个过程:1.制作一个组件:2.在客户端测试这个组件. 一.制作一个组件 1.首先建立一个新类库工程文件 选择File->New->Project->Visual C# Projects->Class Library.填入工程文件名称,并且通过Browse按钮选择文件要

js利用事件的阻止冒泡实现点击空白模态框的隐藏

 点击弹出某个框框,但是,有时候不想操作,就想点击某个空白处,隐藏该框框,关于这一点,下面有个具体的实现 很多时候,我们做前端的时候都会有这样的小功能,点击弹出某个框框,但是,有时候不想操作,就想点击某个空白处,隐藏该框框.假设如下场景,一个小按钮,点击可以弹出一个模态框.    就这么简单,但是我们想要点击空白部分的时候隐藏模态框,加入按钮id:btn,模态框id:model    也许我们最简单的思路就是直接在document上监听一个事件,伪代码如下:    按钮点击弹出事件监听:   代

使用jQuery将多条数据插入模态框的实现代码

 代码如下: //Bootstrap模态框(局部) <div class="modal fade" id="orderDetail"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> </div>   <div class=&q

Bootstrap模态框水平垂直居中与增加拖拽功能_javascript技巧

最近开发一个CMS系统使用上了Bootstrap,在开发一个添加某些选项时,打算弹出一个模态框,但是发现,模态框不会垂直居中到屏幕上,而是在屏幕上方,找了好多资料都没搞定,最终自己试出了一种JS的方法,同时还需要Bootstrap模态框可以拖动,但是发现默认的也不行,翻遍了网络找了出来.现在分享给大家: 原文地址:http://www.panshy.com/articles/201509/webdev-2524.html 以下为Bootstrap模态框拖拽功能的增加方法 $("#myModal&

JS框架之vue.js(深入三:组件1)_javascript技巧

这个要单独写,原文是这么描述vue的组件的:组件(Component)是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素,封装可重用的代码.在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能.在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性扩展. 这个特性我感觉比较难理解,一步步来,看看组件到底是个什么东西? 1.举个栗子 //model层: // 通过extend方式定义一个Vue组件 var MyComponent = Vue.exten

jQuery将多条数据插入模态框的示例代码_jquery

//Bootstrap模态框(局部) <div class="modal fade" id="orderDetail"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> </div> <div class="modal