前言 这个问题困扰了我许久,对于代码和页面我一直有一种洁癖心理,代码格式一定要正,页面的排布也一定要看着舒服。这个问题的起因是前年公司给重新配了一台电脑,连带着显示器也一并进行了更换,新显示器的分辨率是 2k
的,而原先的显示器是 1080p
的,之后我的代码都是在这台 2k
显示器上调试运行。然而在我的显示器上显示正常的页面,到了旧的电脑上就排版错乱了,而其中出现问题频率最高的就是这个 layer
弹出子页面的宽高问题。
问题描述 之前 layer
弹出层的宽高都是通过手动指定的方式来处理,如下:
1 2 3 4 5 6 7 8 9 10 11 12 commonSelf.layerOpenCustome = function (title, content, width, height ) { layer.open({ type : 2 , title : title, shadeClose : false , shade : 0.3 , maxmin : true , area : [width, height], content : content, success : onIframeLoadSuccessEvent }); };
其中 width
和 height
就是指定的宽度和高度,之前指定的值是百分比。但是这个问题就是在不同分辨率的电脑下,百分比对应的值是不同的,这就导致可能在 2k
显示器下显示正常,到了 1080p
显示器下就排版错乱了。
处理办法 layer
窗口由两部分构成,标题栏和内容栏,其中标题栏高度是固定的 - 42px
,内容栏的高度则可以自己调整,而宽度则可以自由指定。因此,可以按照下面的方法进行处理:在 layer
窗口打开后,计算页面所占的高度和宽度,然后再重新调整窗口的大小。
对于我们的页面,只能拿到页面的高度,无法拿到宽度。因为我们页面中的表单都是通过 Bootstrap
的栅格系统进行布局的,这种布局无法确定页面的具体宽度。因此下面的处理都是对窗口高度的调整。
说了思路,就直接上代码了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 function adjustLayerIframeHeight ( ) { let height = $('.ibox' ).height() + 90 ; height = (height < 250 ) ? 250 : height; let parentPageHeight = $('body' , window .parent.document).height(); if (height > parentPageHeight - 20 ) { height = parentPageHeight - 20 ; } let $layerWindow = $('.layui-layer-iframe' , window .parent.document); let $iframe = $('.layui-layer-iframe iframe' , window .parent.document); $layerWindow.height(height); $iframe.height(height - 45 ); let iframeTop = (parentPageHeight - height) / 2 ; if (iframeTop < 10 ) { iframeTop = 10 ; } $layerWindow.css('top' , iframeTop + 'px' ); parent.window.onresize = function ( ) { adjustLayerIframeHeight(); } let pageHeight = $('.ibox' ).height(); window .onmouseup = function ( ) { setTimeout (function ( ) { let currentPageHeight = $('.ibox' ).height(); if (pageHeight !== currentPageHeight) { adjustLayerIframeHeight(); } }, 1 ); } }
注意上面添加了一个 onmouseup
事件,这时因为在我们的页面中,存在一些点击某个按钮会将某些表单 [显示/隐藏] 的情况,这会导致页面高度发生变化,因此这里就重新调整页面的高度。
调整窗口大小的方法写完了,那么应该在什么时候触发呢?开始的时候我想的是在每个页面对应的代码中加上这个方法的调用,但是页面过多,这么处理太过麻烦。因此就想有没有这么一个事件:layer
窗口加载完毕后会回调它。搜索了相关博客,发现有一个 suceess
回调事件,因此处理如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 commonSelf.layerOpenCustome = function (title, content, width, height ) { layer.open({ type : 2 , title : title, shadeClose : false , shade : 0.3 , maxmin : true , area : [width, height], content : content, success : onIframeLoadSuccessEvent }); }; function onIframeLoadSuccessEvent (layero ) { let $childIframe = $(layero).find("iframe" )[0 ].contentWindow; $childIframe.adjustLayerIframeHeight(); $childIframe.$('.ibox table' ).each(function (index, item ) { let $item = $childIframe.$(item); if ($item[0 ].id && $item.is(':visible' )) { $item.on('load-success.bs.table' , function (e, data ) { $childIframe.adjustLayerIframeHeight(); }); } }); }
这里再补充一下,上面的 onIframeLoadSuccessEvent
方法中,额外处理了一种情况:页面中有表格加载完成后重新调整窗口大小 。在测试时,我发现如果子页面存在表格,那么会出现页面高度渲染异常的情况,因此这里的处理是:**在子页面存在没有隐藏且 id
不为空的表格时,表格的数据渲染完成后,再重新调整一次页面的高度。**而这里父页面对子页面资源的调用有必要额外记录一下,因为我在这里卡了许久,必须按照下面的方式调用才能拿到子页面的表格数据:
1 2 3 let $childIframe = $(layero).find("iframe" )[0 ].contentWindow;$childIframe.$(item).bootStrapTable('getData' );
补充 日常使用中发现存在一个问题:如果打开的页面高度比较小,在这个页面中再开一个子页面,子页面的高度因为不能超过父页面的高度,所以显示的内容有限 。针对这个问题,对上面的 adjustLayerIframeHeight()
方法做了如下调整:如果打开的子页面内容高度比父页面要大,那么就调整父页面的高度 。代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 function adjustLayerIframeHeight (height ) { if (height === undefined ) { height = $('.wrapper-content' ).height() + 70 ; height = (height < 250 ) ? 250 : height; } console .log("============================================================" ) console .log("调整页面高度" , $('head title' ).html(), height) let parentPageHeight = $('body' , window .parent.document).height(); if (height > parentPageHeight - 20 ) { if ($('.J_mainContent' , window .parent.parent.document).length === 0 ) { console .log("调整父页面高度" , $('.wrapper-content' )) parent.adjustLayerIframeHeight(height + 70 ); parentPageHeight = $('body' , window .parent.document).height(); } height = parentPageHeight - 20 ; } console .log("目标高度" , height, $('head title' ).html()) let $layerWindow = $('.layui-layer-iframe' , window .parent.document); let $iframe = $('.layui-layer-iframe iframe' , window .parent.document); $layerWindow.height(height); $iframe.height(height - 45 ); let iframeTop = (parentPageHeight - height) / 2 ; if (iframeTop < 10 ) { iframeTop = 10 ; } $layerWindow.css('top' , iframeTop + 'px' ); parent.window.onresize = function ( ) { console .log("父页面高度变化,调整当前页面高度" , $('head title' ).html()) adjustLayerIframeHeight(); } let pageHeight = $('.ibox' ).height(); window .onmouseup = function ( ) { setTimeout (function ( ) { let currentPageHeight = $('.ibox' ).height(); if (pageHeight !== currentPageHeight) { console .log("触发点击事件,调整当前页面高度" , $('head title' ).html()) adjustLayerIframeHeight(); } }, 1 ); } }