这是多年以前用传统JQuery(easyUi)做项目时遇到的问题,今天把解决思路发布出来,也许能帮助到还在使用老架构的同学。
在开发类ERP的后台管理系统时,经常会看到这样的布局结构
每打开一个菜单都是单独打开一个Tab页,easyUi打开Tab页有两种方式:
- 动态增加iframe
- 在同一个Dom树中增加div 的方式
同一Dom树中存在命名污染的问题,包括样式也会互相影响,新增加页面里的样式很可能影响原有页面的布局
因此我们采用iframe的方式实现:
function addTab(subtitle,url,icon,closable){if(!$('#tabs').tabs('exists',subtitle)){$('#tabs').tabs('add',{title:subtitle,content:createFrame(url),closable:(closable==null?true:closable),icon:icon,fit:true});}else{$.messager.confirm('提示',eship.messages.updateTab,function(r){ if (r){ $('#tabs').tabs('select',subtitle);var currTab = $('#tabs').tabs('getSelected');$('#tabs').tabs('update',{tab:currTab,options:{content:createFrame(url)}});}});}tabClose();}function createFrame(url){var s = '
我们在使用时iframe Tab页时,页面中经常会有打开对话框的需求。
因为我们采用了iframe的方式,其实打开对话框是在子页面的iframe的dom中打开的,因此会被主页面遮挡,如图所示:
对话框移动过程中会被Tab标签遮挡,并且无法继续向上移动,并且不同iframe传递参数也比较麻烦,不是很方便,因此决定进行封装,基本原理如下:
封装模态对话框插件
- 判断是否在最顶层dom中执行,如果不在获取到顶层dom对象
- 在最顶层iframe中自动增加一个div,并通过这个div打开模态对话框
- 用堆栈记录打开对话框的相关属性options
- 关闭时,依次调用堆栈中的对话框,并关闭
优点:
- 增加getDialogOption方法,可方便获取当前对话框的option对象,可以方便的通过该对象进行窗口之间的值传递。
- 在关闭时,增加回调方法,可以在关闭时方便的调用父窗体的回调方法。
/** * jQuery dialog * * @author rogerkuo * * easy ui 对话框扩展,自动创建DIV,并将DIV放置在最顶层DOM中,避免对话框被iframe覆盖的情况 */(function($) {$.joyplus = function(){};$.joyplus.messager = function(){};//私有方法,用来负责创建对话框function _joy_show(options) {var defaults = {width : 800,height : 500,title : 'My Dialog',modal : true,onLoad : function(){var topDiaOptions = $.joyplus.getDialogOption();if( topDiaOptions.dialogId != undefined){//如果需要处理对话框连续弹出问题时,对焦点进行处理var topBody = _joy_get_top_body();var ele = $(topBody).find("#" + $.joyplus.getModelDialogId());var inputs = $(ele).find("input");if( inputs.length > 0 ){inputs[0].focus();}}}//dialogId : ""用来判断是否同一窗体,避免同一个业务多次弹出一个对话框,造成对话框堆叠,如果没有,不作处理};var isString = (typeof options == "string");if (isString) {options = {};}var d = {};$.extend(d , options);var topDiaOptions = $.joyplus.getDialogOption();if( topDiaOptions != undefined && topDiaOptions.dialogId != undefined && topDiaOptions.dialogId == d.dialogId ){return;}var isDataFunction = false;//新增dialog传值基础功能,可调用父窗体的方法,获取附加数据if( jQuery.type(d.extdata) == "function"){isDataFunction = true;d.extdata = d.extdata.call(this);}//新增dialog传值grid功能if( jQuery.type(d.grid) == "function"){isDataFunction = true;d.grid = d.grid.call(this);}if(!isDataFunction){d = $.extend(d , options);}_joy_get_options_cache().push(d);var opt = $.extend(defaults, options);opt.onClose = $.joyplus.closeModelDialog;var id = _joy_create_div();var top = _joy_get_top_body();var element = $(top).find("#" + id);$(element).dialog(opt);};//获取最上层的dialog对象function _joy_get_top_dialog() {var stack = _joy_get_dialog_stack();return stack.pop();};//获取对话框堆栈,因为用户可以在对话框上继续点开对话框,因次要记录对话框堆栈//先进后出function _joy_get_dialog_stack() {var top = _joy_get_cahce();return top;};//自动创建div,在dom的最顶层创建function _joy_create_div() {var new_id = _joy_get_new_id();var stack = _joy_get_dialog_stack();stack.push(new_id);$(_joy_get_top_body()).last().append("
这样在使用时,只需调用简单方法即可
function invCageEdit(){var row = $('#invCageDG').datagrid('getSelected');if(row){ var options = {title:"出库包装",height:500,width:1000,contentOverflow:'hidden'}; options.invCageId = row.uuid;//需要传递的扩展属性 options.href = contextPath +'/web/comm/invCageItemDialog.jsp'; options.backFunc = function(data){ //updatePickItem();回调函数 }; $.joyplus.showModelDialog(options);}else{$.joyplus.messager.alert('提示',eship.messages.selectOne,'info');}}