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

参考资料

vue.js dynamic create nest modal
es6 Promise对象
vue-bootstrap-modal

本文已被整理到了《Vue.js前端组件学习教程》,欢迎大家学习阅读。

关于vue.js组件的教程,请大家点击专题vue.js组件学习教程进行学习。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Vue.js弹出模态框组件开发的示例代码

    前言 在开发项目的过程中,经常会需要开发一些弹出框效果,但原生的alert和confirm往往都无法满足项目的要求.这次在开发基于Vue.js的读书WebApp的时候总共有两处需要进行提示的地方,因为一开始就没有引入其他的组件库,现在只好自己写一个模态框组件了.目前只是一个仅满足当前项目需求的初始版本,因为这个项目比较简单,也就没有保留很多的扩展功能.这个组件还是有很多扩展空间的,可以增加更多的自定义内容和样式.这里只介绍如何去开发一个模态框组件,有需要进行更多扩展的,可以根据自己的需求自行开发

  • 利用vue实现模态框组件

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

  • vue实现模态框的通用写法推荐

    在看了element组件的源码后发现,所有模态框其实实现方法都差不多,主要用到了vue在组件化上的双向绑定.代码: <!--查看槽点对话框--> <template lang="html"> <transition name="el-fade-in-linear"> <div draggable="true" @drag="mouseDrag" @dragend="mouse

  • 详解如何用VUE写一个多用模态框组件模版

    对于新手们来说,如何写一个可以多用的组件,还是有点难度的,组件如何重用,如何传值这些在实际使用中,是多少会存在一些障碍的,所以今天特意写一个最常用的模态框组件提供给大家,希望能帮助到您! 懒癌患者直接复制粘贴即可 Modal.vue组件 <template> <!-- 过渡动画 --> <transition name="modal-fade"> <!-- 关闭模态框事件 和 控制模态框是否显示 --> <div class=&qu

  • vue弹出框组件封装实例代码

    新学vue,参考别人封装弹出层组件.好用! 1.你需要先建一个弹出框的模板: //首先创建一个mack.vue <template> <div class="mack" v-if="isShow"> <div class="mackWeb" :style="text.mackStyle"> <div class="title font_b" v-if="t

  • 小程序开发之模态框组件封装

    本文实例为大家分享了小程序模态框组件的封装具体代码,供大家参考,具体内容如下 一.前言 对于模态框肯定大家都知道,诸如:Bootstartp.element-ui.layui等等都有自己的弹出层,并可以之定义内容,但是小程序的弹出层原生的太简单,那么我们如果自定义呢? 其实很简单,就是一个遮罩.一个view内容区就搞定了!接下来看一下我自己封装后的模态框效果: 感觉还可以哈! 二.模态框组件的使用 1.先在使用页面的json注册该组件 { "navigationBarTitleText"

  • vue定义模态框的方法

    本文实例为大家分享了vue定义模态框的具体代码,供大家参考,具体内容如下 <template> <transition name="slide"> <div class="modal" v-show="showModal"> <div class="mask"></div> <div class="modal-dialog"> <

  • 利用Vue构造器创建Form组件的通用解决方法

    前言 在前端平常的业务中,无论是官网.展示页还是后台运营系统都离不开表单,它承载了大部分的数据采集工作.所以如何更好地实现它,是平常工作中的一个重要问题. 在应用Vue框架去开发业务时,会将页面上每个独立的可视/可交互区域拆分为一个组件,再通过多个组件的自由组合来组成新的页面.例如 <template> <header></header> ... <content></content> ... <footer></footer&

  • Vue dialog模态框的封装方法

    前言 这个是基于vue2的模态框封装,仿照elementUI而写的组件. 效果如图 首先我们需要一个遮罩层 <template>     <div class="myDialog">         <div v-if="visable" class="dialog_mask" @click="close"></div>     </div> </templat

  • vue+element 模态框表格形式的可编辑表单实现

    要实现的效果如下,初始化的时候,不可编辑,点击编辑按钮,编辑按钮隐藏,取消编辑按钮显示;部分input输入框变为可编辑 <el-dialog title="营销单详情" width="920px" @close="isEdit = false" class="dialog dialogAdd" custom-class="custom-dialog" :visible.sync="dialo

随机推荐