【Vue】基於Vue封裝的無需頁面聲明的彈出層

說在正文之前:封裝的FastDialog-Vue適用於頁面級Vue開發,即採用引入Vue.js來進行html頁面開發

20190124更新:現已支持Vue工程開發模式中使用dialog,詳情請見:

https://gitee.com/grassprogramming/FastDialog-Vue/tree/vue-using/

最近在使用Vue開發基於springboot的後臺管理系統前端部分,因爲沒有采用webpack進行Vue的單頁面工程開發而是將html與後端進行整合在springboot工程中,而前端Vue涉及到的UI框架中的Modal都是需要事先在頁面中聲明,導致很多頁面邏輯都在一個html中,如果層疊打開多個Modal,那一個html會顯得非常臃腫,代碼邏輯也會很多不利於後續的代碼閱讀與維護,所以就封裝了一個dialog以js的方式引用進頁面,直接調用方法動態將Modal添加到頁面,進行各個頁面的邏輯分離。

項目地址:https://gitee.com/grassprogramming/FastDialog-Vue

說明:

master分支:開發的最早版本,以js,html頁面的方式開發組件

vue分支:以vue工程形式開發的組件,打包js,css供html調用

test分支:測試代碼

演示地址:http://grassprogramming.gitee.io/fastdialog-vue/example.html

dialog會提供以下一些常用功能:

引用vue工程版本的js時需要在Vue初始化時進行變量聲明,即

 var app1 = new Vue({})

調用方法的形式爲app1.$fastdialog.functionname

引用master分支下的直接調用方法即可

1.打開一個html頁面

OpenDialog("111", "打開窗口", "newpage1.html", "600", "1200");

2.打開一個html頁面並指定寬高的單位

OpenDialog("111", "打開窗口", "newpage1.html", "70", "80",null,null,"%");

3.打開一個html頁面傳值並制定回調函數

 OpenDialog("444", "有回調函數並傳參", "newpage1.html", "600", "1200", AfterCloseWithReturn, "125sds");

這些都是調用的OpenDialog方法,我們來看下這個方法定義的參數

function OpenTopDialog(id, title, url, height, width, callback, params, screenunit)

id:dialog標識,title:dialog的head部分的文字,url:打開的頁面地址,height:打開頁面的高度,width:打開頁面的寬度,callback:關閉打開頁面後的父級頁面調用的回調函數,params:父級頁面給打開的子頁面傳遞的參數,screenunit:打開頁面寬高的單位

注:OpenDialog方法是在本級頁面打開窗口,該組件同時提供在頂級窗口打開全局頁面,爲OpenTopDialog,參數完全一致

4.子頁面獲取父級頁面傳遞的參數

 var params = GetParams();

5.關閉頁面

 CloseDialog("page2回傳111111","page3");

看下方法定義

function CloseDialog(ReturnValue,id)

第一個參數爲頁面回傳給父級頁面的值,配合父級頁面使用如下

 function AfterCloseWithReturn(ReturnValue) {
        alert("page1回傳的參數:" + ReturnValue);
    }

第二個參數爲打開的diaog的id,普通打開頁面可以不指定,使用OpenTopDialog的頁面必須指定,後面會詳細說明

6.提供Alert類型的提示dialog

 OpenAlert("提示", "請在規定期限內處理完成!",AfterClose);

看下提示框打開方法的參數定義

function OpenAlert(title, message, callback, btnclosetext)

第一個參數爲提示框標題,第二個參數爲提示內容,第三個參數爲關閉提示框後的回調函數,第四個參數爲關閉按鈕文字的個性化指定,同時還有成功,警告,失敗等提示框,如下

OpenSuccess("提示", "請在規定期限內處理完成!");
OpenWaring("提示", "請在規定期限內處理完成!",null,"知道了");
OpenFail("提示", "請在規定期限內處理完成!");

7.提供Confirm類型確認框的dialog

 OpenConfirm("確認提示", "是否刪除當前數據", function () {

                }, "確認刪除", "取消操作");

看下函數定義,相信一看就懂了

function OpenConfirm(title, message, okcallback, btnoktext, btncanceltext)

接下來說一下開發中到問題的解決方案

1.用原生js開發如何動態請求template模板

如果不是用字符串定義的話,直接請求定義模板的html文件即可,這裏需要注意的是,引用組件到工程的目錄不同,這裏需要自己改下,這是缺點1,缺點2是每次打開dialog會有額外的網絡請求,所以後續版本採用vue工程形式開發,避免了這種問題

    var template;
    var templatepath = GetRootPath() + 'fastdialog/fastdialog-template.html';
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.open("GET", templatepath, false);
    xmlhttp.send();
    template = xmlhttp.responseText;

2.如何讓頁面動態添加Modal

採用獲取dialog的構造函數,動態掛載到頁面的方式(這裏展示的是Vue工程中的代碼)

import dialog from  './dialog.vue'; 
let dialogconstructor  = Vue.extend(dialog);
 var dialoginstace = new dialogconstructor({
        data() {
            return {
                id: id,
                title: title,
                url: url,
                height: height,
                width: width
            }
        },
        methods: {
            close(id) {
                CloseDialogWithOutReturn(id,istop);

            },
            callbackevent(RetrunValue){
                if(callback){
                    if(RetrunValue){
                        callback(RetrunValue);
                    }else{
                        callback();
                    }
                    
                }
            }
        }
    });
dialog.$mount();
document.body.appendChild(dialog.$el);

3.頁面之間,或者說是dialog之間的通信,如傳參,回調函數,關閉的實現方式

實現之初,我是用的是window.postmessage與addeventlistener的方式進行頁面之間的通信,普通打開頁面沒問題,但是一旦和打開頂級頁面混用,就會出現問題,這裏先說下window.postmessage的一些坑

一般邏輯爲,我打開一個二級頁面dialog,我爲父級頁面註冊一個監聽,子頁面關閉後向父級頁面發送message,觸發監聽,進行關閉頁面或者調用回調函數的操作,類似於

//open時 
window.addEventListener('message', receiveMessage, false);
    function receiveMessage(tag) {
        var windowstag = tag.data.toString();
        if(windowstag=='close'){
            dialogInstance.onhidden = callback();
        }else{
            dialogInstance.onhidden = callback(tag.data);
        }
        dialogInstance.close();
    }

//close時
window.parent.postMessage('close', '*');

後面會遇到一個問題是,如果我在page頁面打開一個普通二級頁面page1,在page1中打開頂級頁面page2,那就相當於是page1,和page2的監聽都註冊在page中,回調事件會觸發兩次,即使我可以做到每次註冊時清除監聽,保證只有一個message監聽,但是還是會帶來後續的頁面關閉問題,所以我將回調函數等傳遞性的東西都存在dialog中,在父級頁面中維護dialog數組即可,看如下代碼

fastdialog.OpenDialog=(id, title, url, height, width, callback, params, screenunit) =>{
    var dialog = GetDialogInstance(id, title, url, height, width,callback, false, screenunit);
    dialog.$mount();
    document.body.appendChild(dialog.$el);
    if(window.dialoglist){
        console.log(window.dialoglist)
        for(var i=0;i<window.dialoglist.length;i++){
            if(window.dialoglist[i].id==id){
                window.dialoglist.splice(i,1);
                break;
            }
        }
        window.dialoglist.push({"id":id,"instance":dialog})
    }else{
        var dialoglist = [];
        dialoglist.push({"id":id,"instance":dialog});
        window.dialoglist = dialoglist;
    }
    if (params) {
        var iframe = window.document.getElementById(id + '_fastdialogiframe').contentWindow;
        iframe["fastdialog_params"] = params;
    }

}
fastdialog.CloseDialog=(ReturnValue,id)=> {
    if(id){
        var obj = window.top.document.getElementById(id);
        if(obj){
            for(var i=0;i<window.top.dialoglist.length;i++){
                if(window.top.dialoglist[i].id==id){
                    if(ReturnValue){
                        window.top.dialoglist[i].instance.callbackevent(ReturnValue);
                    }else{
                        window.top.dialoglist[i].instance.callbackevent();
                    }
                    window.top.dialoglist.splice(i,1);
                    break;
                }
            }
            window.top.document.getElementById(id).remove();
         
        }else{
            if(ReturnValue){
                window.parent.dialoglist[0].instance.callbackevent(ReturnValue);
            }else{
                window.parent.dialoglist[0].instance.callbackevent();
            }
            window.parent.dialoglist.splice(0,window.parent.dialoglist.length);
            document.getElementById(id).remove();
           
        }
      
        
    }else{
        if(ReturnValue){
            window.parent.dialoglist[0].instance.callbackevent(ReturnValue);
        }else{
            window.parent.dialoglist[0].instance.callbackevent();
        }
       window.parent.dialoglist.splice(0,window.parent.dialoglist.length);
       var modallist =  window.parent.document.getElementsByClassName("fast-modal-bg");
       for(var i=0;i<modallist.length;i++){
           modallist[i].remove();
       }
       
    }
    
}

其中向打開頁面傳遞參數通過iframe["fastdialog_params"] = params;實現,具體邏輯可以查看源碼看下,需要注意的是dialog還提供右上角的x關閉頁面,關閉時也需要同步維護dialoglist數組

4.使用Vue工程開發如何將dialog以插件的方式提供帶頁面,看代碼就知道將dialog以Vue的全局屬性註冊上去即可

fastdialog.install = function(Vue) {

Vue.prototype.$fastdialog = fastdialog

};

if (typeof window !== 'undefined' && window.Vue) {

window.Vue.use(fastdialog)

}

說在最後:本插件只在chrome瀏覽器做了測試,還希望大家多多提意見,共同進步,如果覺得還不錯的話,記得碼雲給個Star哦

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章