前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Vue】基于Vue封装的无需页面声明的弹出层

【Vue】基于Vue封装的无需页面声明的弹出层

作者头像
code2roc
发布2023-07-19 14:34:03
2240
发布2023-07-19 14:34:03
举报

说在正文之前:封装的FastDialog-Vue适用于页面级Vue开发,即采用引入Vue.js来进行html页面开发

20190124更新:现已支持Vue工程开发模式中使用dialog,详情请见

FastDialog-Vue: 基于vue.js封装的动态渲染弹出层 - Gitee.com

最近在使用Vue开发基于springboot的后台管理系统前端部分,因为没有采用webpack进行Vue的单页面工程开发而是将html与后端进行整合在springboot工程中,而前端Vue涉及到的UI框架中的Modal都是需要事先在页面中声明,导致很多页面逻辑都在一个html中,如果层叠打开多个Modal,那一个html会显得非常臃肿,代码逻辑也会很多不利于后续的代码阅读与维护,所以就封装了一个dialog以js的方式引用进页面,直接调用方法动态将Modal添加到页面,进行各个页面的逻辑分离。

说明:

master分支:开发的最早版本,以js,html页面的方式开发组件

vue分支:以vue工程形式开发的组件,打包js,css供html调用

test分支:测试代码

演示地址:vue组件

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

引用vue工程版本的js时需要在Vue初始化时进行变量声明,即

代码语言:javascript
复制
 var app1 = new Vue({})

调用方法的形式为app1.$fastdialog.functionname

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

1.打开一个html页面

代码语言:javascript
复制
OpenDialog("111", "打开窗口", "newpage1.html", "600", "1200");

2.打开一个html页面并指定宽高的单位

代码语言:javascript
复制
OpenDialog("111", "打开窗口", "newpage1.html", "70", "80",null,null,"%");

3.打开一个html页面传值并制定回调函数

代码语言:javascript
复制
 OpenDialog("444", "有回调函数并传参", "newpage1.html", "600", "1200", AfterCloseWithReturn, "125sds");

这些都是调用的OpenDialog方法,我们来看下这个方法定义的参数

代码语言:javascript
复制
function OpenTopDialog(id, title, url, height, width, callback, params, screenunit)

id:dialog标识,title:dialog的head部分的文字,url:打开的页面地址,height:打开页面的高度,width:打开页面的宽度,callback:关闭打开页面后的父级页面调用的回调函数,params:父级页面给打开的子页面传递的参数,screenunit:打开页面宽高的单位

注:OpenDialog方法是在本级页面打开窗口,该组件同时提供在顶级窗口打开全局页面,为OpenTopDialog,参数完全一致

4.子页面获取父级页面传递的参数

代码语言:javascript
复制
 var params = GetParams();

5.关闭页面

代码语言:javascript
复制
 CloseDialog("page2回传111111","page3");

看下方法定义

代码语言:javascript
复制
function CloseDialog(ReturnValue,id)

第一个参数为页面回传给父级页面的值,配合父级页面使用如下

代码语言:javascript
复制
 function AfterCloseWithReturn(ReturnValue) {
        alert("page1回传的参数:" + ReturnValue);
    }

第二个参数为打开的diaog的id,普通打开页面可以不指定,使用OpenTopDialog的页面必须指定,后面会详细说明

6.提供Alert类型的提示dialog

代码语言:javascript
复制
 OpenAlert("提示", "请在规定期限内处理完成!",AfterClose);

看下提示框打开方法的参数定义

代码语言:javascript
复制
function OpenAlert(title, message, callback, btnclosetext)

第一个参数为提示框标题,第二个参数为提示内容,第三个参数为关闭提示框后的回调函数,第四个参数为关闭按钮文字的个性化指定,同时还有成功,警告,失败等提示框,如下

代码语言:javascript
复制
OpenSuccess("提示", "请在规定期限内处理完成!");
OpenWaring("提示", "请在规定期限内处理完成!",null,"知道了");
OpenFail("提示", "请在规定期限内处理完成!");

7.提供Confirm类型确认框的dialog

代码语言:javascript
复制
 OpenConfirm("确认提示", "是否删除当前数据", function () {

                }, "确认删除", "取消操作");

看下函数定义,相信一看就懂了

代码语言:javascript
复制
function OpenConfirm(title, message, okcallback, btnoktext, btncanceltext)

接下来说一下开发中到问题的解决方案

1.用原生js开发如何动态请求template模板

如果不是用字符串定义的话,直接请求定义模板的html文件即可,这里需要注意的是,引用组件到工程的目录不同,这里需要自己改下,这是缺点1,缺点2是每次打开dialog会有额外的网络请求,所以后续版本采用vue工程形式开发,避免了这种问题

代码语言:javascript
复制
    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工程中的代码)

代码语言:javascript
复制
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,触发监听,进行关闭页面或者调用回调函数的操作,类似于

代码语言:javascript
复制
//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数组即可,看如下代码

代码语言:javascript
复制
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的全局属性注册上去即可

代码语言:javascript
复制
fastdialog.install = function(Vue) {

Vue.prototype.$fastdialog = fastdialog

};

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

window.Vue.use(fastdialog)

}

说在最后:本插件只在chrome浏览器做了测试,还希望大家多多提意见,共同进步,如果觉得还不错的话,记得码云给个Star哦

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-01-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档