說在正文之前:封裝的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哦