• 上下div高度动态自适应--另类处理方案


         这段时间在工作中遇到一个看似较为棘手的问题。问题描述:查询报表页面分为上下两部分,上部分为条件输入区域,下部分为报表展示区域。客户要求做到默认满屏(但要动态适应不同的窗体大小,也就是浏览器窗体用户会手动改变其大小),但上部分条件输入区域有动态变化高度的现象。

         在遇到上述问题,您是否第一反应就是利用window的onresize事件,做尺寸的动态调整。但是条件输入区域某个按钮动态改变了上部分的高度时,我们又应该如何呢。是否有统一的处理方案呢。今儿本人就把我自己的想法和测试提供出来,供大家参考,有疑问或建议欢迎交流和沟通。

    一、上代码

    闲话少说,上代码。首先本人为了处理与IE的兼容性,对现代浏览器,IE浏览器做了区别对待。然后提供了一个工厂类以供使用。

    1.1、 现代浏览器的实现

    /**
            * 现代浏览器处理方案
            */
            function RptAutoHeightForModernBrower(context){
                this.context = context;
                this.$object = null;
            }
            var mPt = RptAutoHeightForModernBrower.prototype;
            mPt.init = function(){
                var object = document.createElement('iframe'), self = this; //object在ie11上onload方法不能执行
                //区元素,绝对定位(父级必须是相对定位,否则参考到body了),四个为0,width、height为100%让其宽、高与父级相同,pointer-events:none(不接受鼠标事件)z-index:层级最低。
                object.onload = function(){ 
                    var context = this;
                    this.contentDocument.defaultView.addEventListener('resize', function(){ 
                        self.context.onResize(context.clientHeight);
                    });
                }
                object.setAttribute('style', 'display:block; position:absolute; border:0px; visibility: hidden; left:0px; right: 0px; top: 0px; bottom: 0px; pointer-events: none; z-index: -1; overflow:hidden;  100%; height: 100%; opacity:0;');
                //object.type = "text/html";
                object.src = "about:blank";
                this.context.$header.appendChild(object);
                this.$object = object;
                //先触发一次 
                this.context.onResize(this.context.$header.clientHeight);
                //window.resize事件
                window.onresize = function(){
                    self.context.onResize(self.context.$header.clientHeight);
                }
            }
            mPt.dispose = function(){
                this.$object.contentDocument.defaultView.removeEventListener('resize');
                this.context.$header.removeChild(this.$object);
            }

         在此处,为了做到兼容IE11(因为Ie11不支持attacheEvent方法,所以也会被判断为现代浏览器),本人创建的DOM,不是使用的object而是使用的iframe,因为在IE下object的onload事件不能触发,而iframe的可能有;并且iframe的边框一定要去掉,否则影响判断。

     

    1.2、ie浏览器的实现

    /**
            * ie的处理方案
            */
            function RptAutoHeightForIE(context){
                this.context = context;
            }
            var iePt = RptAutoHeightForIE.prototype;
            iePt.init = function(){
                var self = this;
                this.context.$header.attachEvent('onresize', function(){
                    self.context.onResize(window.event.srcElement.clientHeight);
                });
                this.context.onResize(this.context.$header.clientHeight);
                //window.resize事件
                window.onresize = function(){
                    self.context.onResize(self.context.$header.clientHeight);
                }
            }
            iePt.dispose = function(){
                this.context.$header.detachEvent('onresize');
            }

         IE浏览器的实现相对简单,因为IE环境下的div天身支持onresize事件。

    1.3、工厂类

    //处理高度自适应的Factory
            function RptAutoHeightFactory(opts){
                this.opts = opts || {};
                this.$wrap = this.opts.wrap || document.getElementsByClassName('rpt-wrap')[0];
                this.$header = this.opts.header || this.$wrap.getElementsByClassName('rpt-header')[0];
                this.$cont = this.opts.cont || this.$wrap.getElementsByClassName('rpt-cont')[0];
                var cxt = {
                    $header: this.$header,
                    onResize: this.resize()
                };
                this.diffVal = 0;
                this.realize = document.attachEvent 
                    ? new RptAutoHeightForIE(cxt) 
                    : new RptAutoHeightForModernBrower(cxt);
            }
            var pt = RptAutoHeightFactory.prototype;
            pt.init = function(){
                var bTop = this.getStyle(this.$header, "border-top-width");
                var bBottom = this.getStyle(this.$header, "border-bottom-width");
                bTop = parseInt(bTop.replace('px', ''), 10);
                bBottom = parseInt(bBottom.replace('px', ''), 10);
                this.diffVal += bTop + bBottom;
                
                var bTop = this.getStyle(this.$cont, "border-top-width");
                var bBottom = this.getStyle(this.$cont, "border-bottom-width");
                bTop = parseInt(bTop.replace('px', ''), 10);
                bBottom = parseInt(bBottom.replace('px', ''), 10);
                this.diffVal += bTop + bBottom;
                
                this.realize.init(); 
    
            }
            pt.resize = function(){
                var $cont = this.$cont, self = this;
                return function(headerHeight){
                    var dist = self.getMaxHeight() - headerHeight - self.diffVal;
                    if(dist > 1 ){
                        $cont.style.height = dist +'px'; //加单位,是为了兼容ie
                    }
                }
            }
            pt.getHeight = function(dom){
                var height = dom.clientHeight;            
                return height;
            }
            pt.getStyle = function(dom, key){
                if(dom.currentStyle){
                    return dom.currentStyle[key];
                }else if(window.getComputedStyle){
                    return window.getComputedStyle(dom, null)[key];
                }
            }
            pt.getMaxHeight = function(){
                return document.documentElement.clientHeight || document.body.clientHeight;
            }

          此处本人在获取style的属性值,使用了getComputedStyle和currentStyle实现的,这民是标准的方法。

    1.4、这样使用

    js代码:

    var irow = 2;
            function addRow(){
                var parent = document.getElementsByClassName('rpt-header')[0];
                var p = document.createElement('p');
                p.innerHTML = "<p>添加第" + irow++ + "行记录</p>";
                parent.appendChild(p);
            }
    
            var autoHeightFactory = new RptAutoHeightFactory();
            autoHeightFactory.init();

    html代码:

    <div class="rpt-wrap">
            <div class="rpt-header">
                <button type="button" onclick="addRow()">添加</button>
                <p>第一行内容</p>
            </div>
            <div class="rpt-cont">
            </div>
        </div>

    css代码:

    html, body{
                margin: 0px;
                padding: 0px;
                height: 100%;
            }
            .rpt-wrap{
                height: inherit;
                overflow: hidden;
            }
            .rpt-header{
                border: 1px solid gray;
                position: relative;
                
            }
            .rpt-cont{
                border: 1px solid red;
            }
  • 相关阅读:
    Chrome等浏览器下出现net::ERR_BLOCKED_BY_CLIENT的解决办法
    document.readyState和document.DOMContentLoaded判断DOM的加载完成
    CSS实现进度条
    H5案例分享:移动端滑屏 touch事件
    Passive Event Listeners——让页面滑动更加流畅的新特性
    禁止蒙层底部页面跟随滚动
    跨域Ajax请求时是否带Cookie的设置
    HTML5 元素拖动
    浅谈程序员的英语学习
    (转载)史上最详细的docker学习手册
  • 原文地址:https://www.cnblogs.com/cqhaibin/p/7441500.html
Copyright © 2020-2023  润新知