vue-彈出框組件

創(chuàng)建一個公用的彈出框組件,包括消息彈出框,確認彈出框,自定義內(nèi)容彈出框

一、創(chuàng)建

1、創(chuàng)建一個基礎(chǔ)彈出框: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;
           //鼠標按下,計算當前元素距離可視區(qū)的距離
            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:{},//各種類型彈出框特有參數(shù)
            initHeight:"",//初始化高度
            initWidth:"400px",//初始化寬度
            minHeight:"",//最小高度
            minWidth:"",//最小寬度
            levelNum:0,//層級
            top:0,//位置;x
            left:0,//位置:y
            title:'提示',//彈出框標題
            message:null,//彈出框內(nèi)容
            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){//如果為最大化窗口,窗口樣式不需改變,僅調(diào)用改變窗口的回調(diào)函數(shù)
                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
            }
        },
//全屏或者恢復(fù)彈窗大小是的回調(diào)
        fullScreenCallback(){
            if (this.options && typeof this.options.fullScreenCallback == "function") {
                this.options.fullScreenCallback();
            }
            if(this.umMoveClass){//已經(jīng)是最大化窗口,點擊后需要恢復(fù)正常大小
                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、創(chuàng)建一個消息彈出框: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、創(chuàng)建一個確認彈出框: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、創(chuàng)建一個自定義出框:自定義.vue

????創(chuàng)建一個任意內(nèi)容vue文件

二、調(diào)用

1、創(chuàng)建供調(diào)用的接口文件: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:{}  //點擊確認傳給回調(diào)的數(shù)據(jù)
*    },
* }
* */
installConfirm(options) {
    options.dialogType='1';
    options.initWidth="400px";
    options.levelNum=10;
    this.initBase(options);
},
/* 彈出框
*  包含:子彈出窗(levelNum為0-9),通知框,確認框,加載中信息框
*  參數(shù):
*  options={
*      titleText:string,標題
*      elemText:string,彈窗的html內(nèi)容
*      levelNum:int,Z軸上的層,分0-9層(可缺,默認值為0)
*      initWidth: string('400px'),初始化寬度(可缺)(此參數(shù)在手機瀏覽器上不生效,采用固定值:96%)
*      initHeight: string,初始化高度(可缺)
*      options:{
*            minWidth: string,最小寬度,僅用于手機瀏覽器(可缺)
*            minHeight: string,最小高度,僅用于手機瀏覽器(可缺)
*            fullScreen:bool,是否顯示全屏按鈕(可缺)
*            fullScreenCallback:func,點擊全屏按鈕的回調(diào)函數(shù)(可缺)
*            closeCallback:func,點擊窗口關(guān)閉事件的回調(diào)函數(shù)(可缺)
*    }
*  }
*/
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: "內(nèi)容",
       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上,點擊關(guān)閉按鈕時會先觸發(fā)drag事件,再點擊一次才會正常關(guān)閉,阻止冒泡也沒用,不知道是何原因。。。。
????新手入門,歡迎指正,接受批評?。。?!

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容