美文网首页
vue-弹出框组件

vue-弹出框组件

作者: 青青草原灰太狼 | 来源:发表于2018-07-26 20:23 被阅读0次

创建一个公用的弹出框组件,包括消息弹出框,确认弹出框,自定义内容弹出框

一、创建

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事件,再点击一次才会正常关闭,阻止冒泡也没用,不知道是何原因。。。。
    新手入门,欢迎指正,接受批评!!!!

github地址:https://github.com/zh-huan/dialog-util

相关文章

网友评论

      本文标题:vue-弹出框组件

      本文链接:https://www.haomeiwen.com/subject/iwcimftx.html