创建一个公用的弹出框组件,包括消息弹出框,确认弹出框,自定义内容弹出框
一、创建
1、创建一个基础弹出框:dialog-base.vue
<template>
<div class="dialog-pop" v-bind:data-level="levelNum" v-bind:style="'z-index:'+zIndex" v-bind:ref="'dialog-'+levelNum">
<div class="dialog-pop-bg"></div>
<div v-bind:class="'dialog-pop-panel '+umMoveClass" v-bind:style="'width:'+initWidth+';height:'+initHeight+';top:'+top+'px;left:'+left+'px;min-height:'+minHeight+';min-width:'+minWidth+';'">
<div class="dialog-pop-panelmain">
<div class="dialog-pop-top">
<span class="dialog-pop-title">{{title}}</span>
<button class="dialog-pop-close" type="button" v-on:click.stop="closedialog"></button>
<button class="dialog-pop-full" type="button" v-on:click.stop="fullScreenCallback" v-if="fullScreen"></button>
<div v-drag="greet" v-bind:style="'height: 100%;position: absolute;top:0;left: 0;right:'+(fullScreen?'60':'30')+'px;'"></div>
</div>
<div class="dialog-pop-body" >
<dialog-message v-if="dialogType=='0'" v-bind:options="options" v-bind:message="message" ></dialog-message>
<dialog-confirm v-if="dialogType=='1'" v-bind:options="options" v-bind:message="message"></dialog-confirm>
<component :is="message" v-if="dialogType=='2'"></component>
</div>
</div>
</div>
</div>
</template>
<script>
import Vue from 'vue';
import '../../css/utils/popupWindow.css'
import '../../css/utils/botton.css'
import message from '../../vue/component/dialog-message.vue';
import confirm from '../../vue/component/dialog-confirms.vue';
Vue.directive('drag',//弹出框拖动指令
{bind:function (el, binding) {
let oDiv = el; //当前元素
let self = this; //上下文
oDiv.onmousedown = function (e) {
let parent=e.target.parentNode.parentNode.parentNode;
//鼠标按下,计算当前元素距离可视区的距离
let disX = e.clientX - parent.offsetLeft;
let disY = e.clientY - parent.offsetTop;
document.onmousemove = function (e) {
//通过事件委托,计算移动的距离
let l = e.clientX - disX;
let t = e.clientY - disY;
//将此时的位置传出去
binding.value({x:l,y:t})
};
document.onmouseup = function (e) {
document.onmousemove = null;
document.onmouseup = null;
};
};
}
}
);
export default {
name: 'dialog-base',
data () {
return {
dialogType:"0",//弹出框类型:0:消息弹出,1:确认弹出,2::自定义弹出
options:{},//各种类型弹出框特有参数
initHeight:"",//初始化高度
initWidth:"400px",//初始化宽度
minHeight:"",//最小高度
minWidth:"",//最小宽度
levelNum:0,//层级
top:0,//位置;x
left:0,//位置:y
title:'提示',//弹出框标题
message:null,//弹出框内容
fullScreen:false,//是否全屏
zIndex:-1,//显示层级
oldPosition:{},//存储初始位置
umMoveClass:''
}
},
components:{
"dialog-message":message,
"dialog-confirm": confirm,
},
mounted () {
this.fullScreen=this.options&&this.options.fullScreen?true:false;
this.minHeight=this.options&&this.options.minHeight?this.options.minHeight:"";
this.minWidth=this.options&&this.options.minWidth?this.options.minWidth:"";
//DOM渲染完成
this.$nextTick(function () {
this.windowResize();
});
window.onresize = (function resize() {
this.windowResize();
}).bind(this);
},
methods: {
greet(val){
let x=val.x;
let y=val.y;
if(x<0)x=0;
if(y<0)y=0;
this.left=x;
this.top=y;
},
closedialog(e){
if (this.options && typeof this.options.closeCallback == "function") {
this.options.closeCallback();
}
let pop=this.$refs['dialog-'+this.levelNum];
if(pop){
document.querySelector('body').removeChild(pop);
}
},
//窗口改变时间
windowResize(){
if(this.umMoveClass){//如果为最大化窗口,窗口样式不需改变,仅调用改变窗口的回调函数
if (this.options && typeof this.options.fullScreenCallback == "function") {
this.options.fullScreenCallback();
}
return;
}
let winWidth=document.documentElement.clientWidth;
let winHeight=document.documentElement.clientHeight;
let width=this.$refs['dialog-'+this.levelNum].getElementsByClassName("dialog-pop-panel")[0].offsetWidth;
let height=this.$refs['dialog-'+this.levelNum].getElementsByClassName("dialog-pop-panel")[0].offsetHeight;
this.top= Math.max(20,(winHeight-height)/2-10);
this.left=(winWidth-width)/2;
if(this.top<0)this.top=0;
if(this.left<0)this.left=0;
this.zIndex=1000+this.levelNum*100;
this.oldPosition={
oldHeigth:this.initHeight,
oldWidth:this.initWidth,//初始化宽度
oldtop:this.top,//位置;x
oldleft:this.left,//位置:y
}
},
//全屏或者恢复弹窗大小是的回调
fullScreenCallback(){
if (this.options && typeof this.options.fullScreenCallback == "function") {
this.options.fullScreenCallback();
}
if(this.umMoveClass){//已经是最大化窗口,点击后需要恢复正常大小
this.umMoveClass='';
this.top=this.oldPosition.oldtop;
this.left=this.oldPosition.oldleft;
this.initWidth=this.oldPosition.oldWidth;
this.initHeight=this.oldPosition.oldHeigth;
}else{
this.umMoveClass='dialog-pop-ummove';
this.top=0;
this.left=0;
this.initWidth="100%";
this.initHeight="100%";
}
}
}
}
</script>
2、创建一个消息弹出框:dialog-message.vue
<template>
<div class="dialog-msg">
<div class="dialogmsg-content">{{message}}</div>
<i v-bind:class="'dialogicon '+iClass"></i>
<div class="dialogmsg-bottom">
<button class="dialogbtn-detail" type="button" v-if="options.detailMessage!=''" v-on:click="showDetail"><i v-bind:class="detailClass"></i>显示详细信息</button>
<button class="mt-btn__type1 dialogbtn-ok" type="button" v-on:click="closedialog">确认</button>
<transition name="fade">
<div class="dialogmsg-detail" v-if="isShowDetail" v-bind:style="'overflow:'+overflow">
{{options.detailMessage}}
</div>
</transition>
</div>
</div>
</template>
<script>
export default {
name: 'dialog-message',
props:{
message:{
type:String,
required:true
},
options:{
type:Object,
required:true,
}
},
data () {
return {
isShowDetail:false,
levelNum:20,
iClass:'dialogicon-1',
detailClass:'dialogbtn-ddown',
overflow:'hidden'
}
},
mounted () {
if(this.options&&this.options.iType){
this.iClass="dialogicon-"+this.options.iType;
}
},
methods: {
closedialog:function () {
if(this.options&&typeof this.options.callbackMessageOK === "function"){
this.options.callbackMessageOK(111);
}
this.$parent.closedialog();
},
showDetail:function(){
if(this.isShowDetail){
this.isShowDetail=false;
this.overflow="hidden";
this.detailClass="dialogbtn-ddown"
}else{
this.isShowDetail=true;
this.detailClass="dialogbtn-dup";
this.overflow="auto";
}
}
}
}
</script>
2、创建一个确认弹出框:dialog-confirms.vue
<template>
<div class="dialog-msg">
<div class="dialogconf-content">
{{message}}
</div>
<i class="dialogicon dialogicon-4"></i>
<div class="dialogconf-bottom">
<button class="mt-btn__type1 dialogbtn-yes" type="button" v-on:click="yesCallbackFunction"> {{yesText}} </button>
<button class="mt-btn__type3 dialogbtn-no" type="button" v-on:click="noCallbackFunction"> {{noText}} </button>
</div>
</div>
</template>
<script>
export default {
name: 'dialog-confirm',
props:{
message:{
type:String,
required:true
},
options:{
type:Object,
required:true,
}
},
data () {
return {
yesText:'确认',
noText:'取消',
confirmData:null,
}
},
mounted () {
if(this.options&&this.options.yesText){
this.yesText=this.options.yesText;
}
if(this.options&&this.options.noText){
this.noText=this.options.noText;
}
if(this.options&&this.options.data){
this.confirmData=this.options.data;
}
this.iClass="dialogicon-"+this.iType;
},
methods: {
yesCallbackFunction () {
try{
if(this.options&&typeof this.options.yesCallbackFunction === "function"){
let result=this.options.yesCallbackFunction(this.confirmData);
if (typeof result == "boolean" && result == false) {
return;
}
}
}
catch(e){
}
this.closeDialog();
},
noCallbackFunction(){
try{
if(this.options&&typeof this.options.noCallbackFunction === "function"){
let result=this.options.noCallbackFunction(this.confirmData);
if (typeof result == "boolean" && result == false) {
return;
}
}
}
catch(e){
}
this.closeDialog();
},
closeDialog(){
this.confirmData=null;
this.$parent.closedialog();
}
},
}
</script>
3、创建一个自定义出框:自定义.vue
创建一个任意内容vue文件
二、调用
1、创建供调用的接口文件:dialogUtil.js
import Vue from 'vue'
import Message from '../../vue/component/dialog-base.vue'
export default{
installDialog(){
return {
message:this.installMessage.bind(this),
confirm:this.installConfirm.bind(this),
subPop:this.installSubPop.bind(this),
}
},
/*
* 消息弹窗框
* options={
* title:'',
* message:'',
* options:{
* detailMessage:'',
* iType:'1',//枚举值:1,2,3(警告类型图标,提示类型图标等,配合css使用)
* callbackMessageOK:func
* },
* }
* */
installMessage(options) {
options.dialogType='0';
options.initWidth="400px";
options.levelNum=20;
this.initBase(options);
},
/*
* 确认弹窗框
* options={
* title:"",
* message:"",
* options:{
* yesCallbackFunction:func,
* noCallbackFunction:func,
* yesText:'',
* noText:'',
* data:{} //点击确认传给回调的数据
* },
* }
* */
installConfirm(options) {
options.dialogType='1';
options.initWidth="400px";
options.levelNum=10;
this.initBase(options);
},
/* 弹出框
* 包含:子弹出窗(levelNum为0-9),通知框,确认框,加载中信息框
* 参数:
* options={
* titleText:string,标题
* elemText:string,弹窗的html内容
* levelNum:int,Z轴上的层,分0-9层(可缺,默认值为0)
* initWidth: string('400px'),初始化宽度(可缺)(此参数在手机浏览器上不生效,采用固定值:96%)
* initHeight: string,初始化高度(可缺)
* options:{
* minWidth: string,最小宽度,仅用于手机浏览器(可缺)
* minHeight: string,最小高度,仅用于手机浏览器(可缺)
* fullScreen:bool,是否显示全屏按钮(可缺)
* fullScreenCallback:func,点击全屏按钮的回调函数(可缺)
* closeCallback:func,点击窗口关闭事件的回调函数(可缺)
* }
* }
*/
installSubPop(options) {
options.dialogType='2';
options.levelNum=0;
this.initBase(options);
},
initBase(options){
var message = Vue.extend(Message)
var component = new message({
data: options
}).$mount()
document.querySelector('body').appendChild(component.$el)
}
}
2、引入消息弹窗组件
import dialogMessage from '../utils/dialogUtil.js';
Vue.prototype.$installdialog = dialogMessage.installDialog();
3、使用弹窗
//消息弹窗
let options= {
title: "提示",
message: "内容",
options: {
detailMessage: "detail",
iType: "2",
//callbackMessageOK:this.yesCallback.bind(this)
}
};
this.$installdialog.message(options);
//确认弹窗
let options={
title:"提示",
message:"确定是否?",
options:{
yesCallbackFunction:this.yesCallbackFunction,
// noCallbackFunction:this.noCallbackFunction,
// yesText:'',
// noText:'',
data:{
test:'111'
}
}
}
this.$installdialog.confirm(options);
//自定义弹窗
import page from "./page.vue";
let options={
title:"弹出",
message:page,
initWidth:"300px",
initHeight:"200px",
options:{
minWidth:"400px",
minHeight:"300px",
fullScreen:true,
fullScreenCallback:this.fullScreenCallback,
closeCallback:this.yesCallback,
}
}
this.$installdialog.subPop(options);
碰到一个问题 如果把v-drag 绑定到dialog-pop-top上,点击关闭按钮时会先触发drag事件,再点击一次才会正常关闭,阻止冒泡也没用,不知道是何原因。。。。
新手入门,欢迎指正,接受批评!!!!