现在的位置: 首页 > easyui > Grid > datagrid > 正文
jQuery EasyUI Datagrid组件fixRowHeight接口源码分析
2013年03月21日 datagrid ⁄ 共 7179字 评论数 2 ⁄ 被围观 13,270 views+
文章目录
[隐藏]

在庞大的Datagrid组件中,有个不起眼的接口:fixRowHeight,这个接口是不是真的是像看起来的那样不起眼呢?就其对外的用途来讲可能是不起眼,因为很少情况会用到这个接口。

然而这个对外接口调用的内部方法确实相当相当重要的,可以说没有它就没有Datagrid华丽的外衣,我将这个内部方法翻译为setRowHeight。通过对源码的分析,我们很容易知道,这个内部方法担负着同步“frozenColumns”和“普通columns”高度等重要功能,话不多说,请直接看源码:

对外接口定义

  1. fixRowHeight: function(jq, param) {   
  2.     return jq.each(function() {   
  3.         setRowHeight(this, param);   
  4.     });   
  5. }  

setRowHeight方法

  1. /**  
  2.  * 内部接口,设置行高  
  3.  * @param {DOM object} target   datagrid宿主table对应的DOM对象  
  4.  * @param {number} rowIndex 行索引  
  5.  * @param {boolean} editing  是否在编辑状态(妈的,想了好阵子才想起这个鸟参数是用于可编辑表格,于是翻译为editing)  
  6.  */  
  7.   
  8. function setRowHeight(target, rowIndex, editing) {   
  9.     //一行毫无用处的代码   
  10.     var rows = $.data(target, "datagrid").data.rows;   
  11.     var opts = $.data(target, "datagrid").options;   
  12.     var dc = $.data(target, "datagrid").dc;   
  13.     /**
  14.      * 需要同步"冻结列视图view1"和"普通列视图view2"两个table行高的情况,  
  15.      * 为什么要同步呢?因为两个视图包含了两个不同的表格,不同表格间行跟行之间当然无法自动等高了,  
  16.      * 又有哪些情况需要同步两个视图包含的两个table的行高呢?目前为止,有以下三种情况需要同步:  
  17.      * 1.冻结列视图view1不为空(显示行号或者存在frozenColumns的时候),且nowrap属性为false,即文字自动换行;  
  18.      * 2.冻结列视图view1不为空(显示行号或者存在frozenColumns的时候),且autoRowHeight属性为true,即行号取决于内容;  
  19.      * 3.冻结列视图view1不为空(显示行号或者存在frozenColumns的时候),且有row处于可编辑状态;  
  20.      */  
  21.     if(!dc.body1.is(":empty") && (!opts.nowrap || opts.autoRowHeight || editing)) {   
  22.         //如果入参存在行索引   
  23.         if(rowIndex != undefined) {   
  24.             //获取冻结列视图view1对应的tr   
  25.             var tr1 = opts.finder.getTr(target, rowIndex, "body", 1);   
  26.             //获取普通列视图view2对应的tr   
  27.             var tr2 = opts.finder.getTr(target, rowIndex, "body", 2);   
  28.             //取tr1和tr2高度的最大值,并且将tr1和tr2的高度都设置为这个最大值。   
  29.             setTrHeight(tr1, tr2);   
  30.         }   
  31.         //如果没有行索引入参,则同步所有数据行高度。   
  32.         else {   
  33.             //获取所有冻结列视图数据行   
  34.             var tr1 = opts.finder.getTr(target, 0, "allbody", 1);   
  35.             //获取所有普通列视图数据行   
  36.             var tr2 = opts.finder.getTr(target, 0, "allbody", 2);   
  37.             //设置等高值   
  38.             setTrHeight(tr1, tr2);   
  39.             //如果存在footer的话,footer部分的tr(不在数据行范围内)也要同步行高   
  40.             if(opts.showFooter) {   
  41.                 //获取所有冻结列视图footer行   
  42.                 var tr1 = opts.finder.getTr(target, 0, "allfooter", 1);   
  43.                 //获取所有普通列视图footer行   
  44.                 var tr2 = opts.finder.getTr(target, 0, "allfooter", 2);   
  45.                 //设置等高值   
  46.                 setTrHeight(tr1, tr2);   
  47.             }   
  48.         }   
  49.     }   
  50.     resizePanel(target);   
  51.     //如果datagrid的height属性为auto,则根据实际数据行高度计算datagrid高度   
  52.     if(opts.height == "auto") {   
  53.         var body1 = dc.body1.parent();   
  54.         var body2 = dc.body2;   
  55.         var height = 0;   
  56.         var width = 0;   
  57.         body2.children().each(function() {   
  58.             var c = $(this);   
  59.             if(c.is(":visible")) {   
  60.                 height += c._outerHeight();   
  61.                 if(width < c._outerWidth()) {   
  62.                     width = c._outerWidth();   
  63.                 }   
  64.             }   
  65.         });   
  66.         if(width > body2.width()) {   
  67.             height += 18;   
  68.         }   
  69.         body1.height(height);   
  70.         body2.height(height);   
  71.         dc.view.height(dc.view2.height());   
  72.     }   
  73.     dc.body2.triggerHandler("scroll");   
  74.     /**
  75.      * 取tr1和tr2高度的最大值,并且将tr1和tr2的高度都设置为这个最大值。  
  76.      * @param {DOM object array} domtr1 tr1,注意了是个数组  
  77.      * @param {DOM object array} domtr2 tr2,也是个数组  
  78.      */  
  79.   
  80.     function setTrHeight(domtr1, domtr2) {   
  81.         for(var i = 0; i < domtr2.length; i++) {   
  82.             var tr1 = $(domtr1[i]);   
  83.             var tr2 = $(domtr2[i]);   
  84.             tr1.css("height""");   
  85.             tr2.css("height""");   
  86.             var maxHeight = Math.max(tr1.height(), tr2.height());   
  87.             tr1.css("height", maxHeight);   
  88.             tr2.css("height", maxHeight);   
  89.         }   
  90.     };   
  91. };  

resizePanel方法

setRowHeight方法用到了resizePanel,resizePanel这个方法也是一个内部的方法,并为对外提供,Datagrid内部多处使用了这个方法,我将其翻译为resizePanel应该较为贴切了,这个方法肩负着布局panel的作用,来看源码:

  1. /**  
  2.  * 重新洗牌,计算datagrid容器布局  
  3.  * @param  {DOM object} target datagrid宿主table对应的DOM对象  
  4.  * @return {undefined}        未返回结果  
  5.  */  
  6.   
  7. function resizePanel(target) {   
  8.     var opts = $.data(target, "datagrid").options;   
  9.     var dc = $.data(target, "datagrid").dc;   
  10.     var panel = $.data(target, "datagrid").panel;   
  11.     var panelWidth = panel.width();   
  12.     var panelHeight = panel.height();   
  13.     var view = dc.view;   
  14.     var view1 = dc.view1;   
  15.     var view2 = dc.view2;   
  16.     var view1Header = view1.children("div.datagrid-header");   
  17.     var view2Header = view2.children("div.datagrid-header");   
  18.     var view1HeaderTable = view1Header.find("table");   
  19.     var view2HeaderTable = view2Header.find("table");   
  20.     view.width(panelWidth);   
  21.     //这个地方可以使用$.data(target,'datagrid').dc.header1直接获取到,为何还要用jquery去检索DOM是个疑问。   
  22.     //div.datagrid-header-inner在easyui.css中的宽度是定义为10000的。   
  23.     var header1 = view1Header.children("div.datagrid-header-inner").show();   
  24.     //根据标题的表格宽度设置view1宽度   
  25.     //你妈的,header1.find("table")不就是前面的view1HeaderTable么,这里又用jquery检索,真特么的没事找事干。   
  26.     view1.width(header1.find("table").width());   
  27.     if(!opts.showHeader) {   
  28.         header1.hide();   
  29.     }   
  30.     //view2的宽度设置为panel去除view1的宽度   
  31.     view2.width(panelWidth - view1._outerWidth());   
  32.     //统一header body footer的宽度   
  33.     view1.children("div.datagrid-header,div.datagrid-body,div.datagrid-footer").width(view1.width());   
  34.     view2.children("div.datagrid-header,div.datagrid-body,div.datagrid-footer").width(view2.width());   
  35.     var hh;   
  36.     view1Header.css("height""");   
  37.     view2Header.css("height""");   
  38.     view1HeaderTable.css("height""");   
  39.     view2HeaderTable.css("height""");   
  40.     //获取两个视图表格较大的高度值,以此值设置两表格同步高度   
  41.     hh = Math.max(view1HeaderTable.height(), view2HeaderTable.height());   
  42.     view1HeaderTable.height(hh);   
  43.     view2HeaderTable.height(hh);   
  44.     view1Header.add(view2Header)._outerHeight(hh);   
  45.     //如果高度不是auto的话,则处理frozenRows   
  46.     if(opts.height != "auto") {   
  47.         var bodyHeight = panelHeight - view2.children("div.datagrid-header")._outerHeight() - view2.children("div.datagrid-footer")._outerHeight() - panel.children("div.datagrid-toolbar")._outerHeight();   
  48.         panel.children("div.datagrid-pager").each(function() {   
  49.             bodyHeight -= $(this)._outerHeight();   
  50.         });   
  51.         //设置frozenRows所在表格为绝对定位脱离普通文档流,它像一只断了线的气球,嗖的一下就想往云彩里飘   
  52.         //可惜啊,它被天花板挡住了,只能跟吊死鬼一样,挂在天花板下,这个天花板就是dc.view1以及dc.view2了,因为dc.view1以及dc.view2也是绝对定位。   
  53.         //既然dc.view1以及dc.view2也是绝对定位,他们肯定也想往云彩里钻(可能是云彩里棉花糖多),不过总有一块更高的天花板会挡住他们的去路。   
  54.         //top属性的设置,决定了frozenRows会悬浮在离天花板dc.header2._outerHeight()距离处。   
  55.         dc.body1.add(dc.body2).children("table.datagrid-btable-frozen").css({   
  56.             position: "absolute",   
  57.             top: dc.header2._outerHeight()   
  58.         });   
  59.         //获得frozenRows的高度   
  60.         var frozenRowsHeight = dc.body2.children("table.datagrid-btable-frozen")._outerHeight();   
  61.         //为啥要设置marginTop呢,因为有个吊死鬼吊在半空,没有margin的话,非frozenRows的内容就得被吊死鬼挡住一部分   
  62.         //当然了,高度得把frozenRowsHeight去掉,否则有了marginTop,高度又不减少,会把两个view撑出额外的高度   
  63.         view1.add(view2).children("div.datagrid-body").css({   
  64.             marginTop: frozenRowsHeight,   
  65.             height: (bodyHeight - frozenRowsHeight)   
  66.         });   
  67.         //到这里,我们应该理解一个问题了,为何满足opts.height != "auto"条件,才会进行这段运算   
  68.         //如果高度为auto的话,他娘的肯本不会有垂直滚动条,那么你冻结的rows还有什么个鸟意义呢   
  69.     }   
  70.     view.height(view2.height());   
  71. };  

目前有 2 条留言 其中:访客:2 条, 博主:0 条

  1. 粉丝 : 2015年02月10日10:03:14  -49楼 @回复 回复

    我冻结了3列,并且有一列合并了单元格(竖向),然后view2的行高就计算出错了,两个的行就错位了,请问怎么回事

  2. 老猪 : 2015年08月21日17:11:13  -48楼 @回复 回复

    不知道行高要怎么设置。 不通过样式表修改的话

给我留言

留言无头像?


×