基本上每个项目都需要用到模态框组件,由于在最近的项目中,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. }
  13. .modal-dialog {
  14. position: absolute;
  15. left: 50%;
  16. top: 0;
  17. transform: translate(-50%,0);
  18. width: 690/@rate;
  19. padding: 50/@rate 40/@rate;
  20. background: #fff;
  21. }
  22. .modal-backup {
  23. position: fixed;
  24. top: 0;
  25. right: 0;
  26. bottom: 0;
  27. left: 0;
  28. z-index: 1000;
  29. background: rgba(0, 0, 0, 0.5);
  30. }

这里只是一些基本样式,没什么好说的,这次项目是在移动端,用了淘宝的自适应布局方案,@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. // 取消按钮
  11. cancelfunction() {
  12. this.$dispatch('transmit',this.events.cancel);
  13. }
  14. // 确定按钮
  15. submit: function() {
  16. this.$dispatch('transmit',this.events.submit);
  17. }

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

  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中为每个对话框都写一次,有点麻烦。

参考资料

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

用vue实现模态框组件的更多相关文章

  1. Angular2+之模态框-使用ngx-bootstrap包中的模态框组件实现

    模态框是项目中经常会用到的一个公共功能,通常会被用左提示框或者扩展选项框. 下面,我用一个小例子来简单展示实现模态框功能的过程: 1.为项目加包: ng add ngx-bootstrap 2.在xx ...

  2. 教你使用HTML5原生对话框元素,轻松创建模态框组件

    HTML 5.2草案加入了新的dialog元素.但是是一种实验技术. 以前,如果我们想要构建任何形式的模式对话框或对话框,我们需要有一个背景,一个关闭按钮,将事件绑定在对话框中的方式安排我们的标记,找 ...

  3. 解决vue中模态框内数据和外面的数据绑定的问题

    1.做表格的修改,把整条数据传到模态框做修改,但是出现模态框改变数据没有保存时,表格的数据也会跟着改变,我想实现保存以后表格数据才会改变的功能. html:使用item整条数据都上传过去了,在upda ...

  4. vue 自定义modal 模态框组件

    参数名 类型 说明 visible Boolean 是否显示,默认false title String 标题 update:visible Boolean 更新visible, 使用:visible. ...

  5. 打造 Vue.js 可复用组件

    Vue.js 是一套构建用户界面的渐进式框架.我们可以使用简单的 API 来实现响应式的数据绑定和组合的视图组件. 从维护视图到维护数据,Vue.js 让我们快速地开发应用.但随着业务代码日益庞大,组 ...

  6. vue2.X 自定义 模态框 modal

    1.自定义 modal Modal.vue <!-- 模态框 --> <template> <div class="modal-mask" v-sho ...

  7. 用jQuery写了一个模态框插件

    用jQuery写了一个模态框插件 大家觉得下面的框框好看么, 水印可以去掉(这个任务交给你们了(- o -)~zZ); "info"框 $("div").con ...

  8. 每日质量NPM包模态框_react-modal

    一.react-modal 官方定义: Accessible modal dialog component for React.JS 理解: 一个容易使用的React模态框组件 二.用法 有时候我们不 ...

  9. 基于Vue.js PC桌面端弹出框组件|vue自定义弹层组件|vue模态框

    vue.js构建的轻量级PC网页端交互式弹层组件VLayer. 前段时间有分享过一个vue移动端弹窗组件,今天给大家分享一个最近开发的vue pc端弹出层组件. VLayer 一款集Alert.Dia ...

随机推荐

  1. php+mysql+apache+nginx

    http://www.cnblogs.com/xiaoluo501395377/archive/2013/04/07/3003278.html 安装mysql rpm -qa | grep mysql ...

  2. 【C语言学习】《C Primer Plus》第11章 字符串和字符串函数

    学习总结 1.字符串(character String)是以空字符串(\o)结尾的char数组. 2.gets()方法代表get String,它从系统的标准输入设备(通常是键盘)获取一个字符串,当字 ...

  3. DeviceOne接受了DevStore的专访

    DevStore隶属深圳尺子科技有限公司,DevStore所有内容(资讯.数据.工具|服务.资源文章.问答……)都贯穿整个项目的生命周期,无论你是设计人员.开发人员.推广人员还是运营人员都可在此找到你 ...

  4. 在GitHub注册账户的过程

    (1)第一步:首先起一个属于自己用户的名字(username),用户名字只能包含字母数字的字符或者单个连字符,不能只用单个连字符开始或者结束(only contain alphanumeric cha ...

  5. var与this,{}与function 小记

    JavaScript var是用来定义一个变量,this常用来定义或调用一个属性或方法.但是在全局范围内,this和var定义变量是等价的. window console.log('window:', ...

  6. Wix 安装部署教程(八) 自动生成XML小工具

    这个功能类似于Heat.exe,指定文件夹,生成对应的WIX标签.Winform做的,代码简单,生成的标签需要粘贴到对应的目录才能使用,并不是一步到位. 需要设定两个参数,一个是文件夹路径,一个是文件 ...

  7. [.net 面向对象编程基础] (11) 面向对象三大特性——封装

    [.net 面向对象编程基础] (11) 面向对象三大特性——封装 我们的课题是面向对象编程,前面主要介绍了面向对象的基础知识,而从这里开始才是面向对象的核心部分,即 面向对象的三大特性:封装.继承. ...

  8. 走进AngularJs(三)自定义指令-----(上)

    一.有感而发的一些话 在学习ng之前有听前辈说过,angular上手比较难,初学者可能不太适应其语法以及思想.随着对ng探索的一步步深入,也确实感觉到了这一点,尤其是框架内部的某些执行机制,其复杂程度 ...

  9. 换个角度理解云计算之HDFS

    学习云计算,必然得了解Hadoop,而Hadoop中的HDFS(分布式文件系统)是一个基础,接下来就写一下我所理解的HDFS. 有一个很有特别的村庄,村庄里面有一个很牛逼的人,叫做“大哥”,村民们都信 ...

  10. MVVM架构~knockoutjs系列之数组的$index和$data

    返回目录 已经写了很多knockoutjs的文章了,今天在review代码时,忽然看到一个问题,在knockout环境下,如何遍历一个简单的数组?对于遍历对象组件的数组来说,很容易,直接foreach ...