复杂grid 支持多表头,固定表头,冻结列,合并行

xiaoxiao2021-02-28  68

该组件支持三种渲染形态,因为有些简单的表格没必要去做太复杂的处理。

支持自适应页面宽度和可以设置固定宽度,理论上是所有浏览器都支持,但是因为我引用了一些工具类,处理数组的filter、map 所以向前兼容可以自己实现这些方法

第一种:不需要固定头和列,纯普通表格。

第二种:只需要固定头,滚动内容区域 

第三种:需要固定列。

本身想采用虚拟DOM来常渲染,因为这种组件对性能消耗挺大,后面想了一下本来就是来提供大家一个思路的例子没必要写的太复杂,现在的话写的还算比较简单只有几百行,如果代码量很多对于一个想研究这类组件的同学可能压力很多。

     require(['yg'], function () {                     (function () {                         function FTable(columns)                         {                             this.columns = columns;                             this.unionColumns = concatColumn(columns);                                                          this.colgroup = null;                             this.thead = null;                             this.tbody = null;                             this.wrapper = $('<div>');                             this.element = $('<table class="fx-table">').appendTo(this.wrapper);                             this.initColgroup();                         }                         FTable.prototype.getFixedColumns=function()                         {                             return Yg._.filter(this.unionColumns, { fixed: true })                         }                         FTable.prototype.forColumnWidth = function (viewWidth,callback) {                             var unionColumns = this.unionColumns, count = unionColumns.length, totalWidth = 0, surplusWidth, columnWidth;                             function getValue(value) {                                 value = parseInt(value);                                 return String(value).indexOf('%') != -1 ? value / 100 * viewWidth : value;                             }                             for (var i = 0; i < count; i++) {                                 if (callback(unionColumns[i])===true) {                                     totalWidth += getValue(unionColumns[i].width);                                 }                             }                             return totalWidth;                         }                         FTable.prototype.getColumnWidth = function (viewWidth) {                             return Math.max(this.forColumnWidth(viewWidth, function (c) { return Yg._.has(c, 'width');}), viewWidth)                         }                         FTable.prototype.getFixedColumnWidth = function (viewWidth) {                             return this.forColumnWidth(viewWidth, function (c) { return Yg._.has(c, 'width')&&c.fixed; });                         }                         FTable.prototype.getHeight=function()                         {                             return this.element.outerHeight();                         }                         FTable.prototype.getWidth = function () {                             return this.element.outerWidth();                         }                         FTable.prototype.setWidth = function (width)                         {                             this.element.width(width);                         }                         FTable.prototype.setHeight = function (height) {                             this.element.height(height);                         }                         FTable.prototype.setOuterWidth = function (width) {                             this.wrapper.width(width);                         }                         FTable.prototype.setOuterHeight = function (height) {                             this.wrapper.height(height);                         }                         FTable.prototype.setStyle=function(styles)                         {                             this.element.css(styles);                         }                         FTable.prototype.clone=function()                         {                             return new FTable(this.columns);                         }                              FTable.prototype.initColgroup=function()                         {                             this.colgroup = new Colgroup(this.unionColumns);                         }                         FTable.prototype.setHead = function (thead)                         {                             this.thead = thead;                         }                         FTable.prototype.initHead = function (visibleNoFixed)                         {                             this.thead = new FTHead(this.columns, visibleNoFixed);                         }                         FTable.prototype.initBody = function (visibleNoFixed) {                             this.tbody = new FTBody(this.unionColumns, visibleNoFixed);                         }                         FTable.prototype.renderData=function(data)                         {                             this.tbody.renderData(data);                             this.trigger('onRenderData',data);                         }                                 FTable.prototype.render=function(parent)                         {                             this.colgroup.render(this.element);                             this.thead && this.thead.render(this.element);                             this.tbody && this.tbody.render(this.element);                             parent.append(this.wrapper);                         }                         Yg.extend(FTable.prototype, Yg.Events);                         function Colgroup(columns)                         {                             this.element = $('<colgroup>');                             Yg.each(columns, Yg.bind(this.addCol, this));                         }                         Colgroup.prototype.addCol = function (column) {                             var col = $('<col>');                             if (column.hasOwnProperty('width')) {                                 col.css({ width: column.width });                             }                             col.appendTo(this.element);                         }                         Colgroup.prototype.render=function(parent)                         {                             parent.append(this.element);                         }                         function FTHead(columns, visibleNoFixed)                         {                             this.visibleNoFixed = visibleNoFixed;                             this.element = $('<thead>');                             this.addRow(columns);                         }                         FTHead.prototype.rowDepth = function (columns, len)                         {                             var childColumns = [];                             for (var i = 0, length = columns.length; i < length; i++) {                                 if (Yg._.has(columns[i], 'columns') && columns[i].columns.length > 0)                                 {                                     childColumns = childColumns.concat(columns[i].columns);                                 }                             }                             if(childColumns.length>0)                             {                                 return this.rowDepth(childColumns,len+1);                             }                             return len;                         }                         FTHead.prototype.colDepth = function (columns, len) {                             var childColumns = [], length = columns.length;                             for (var i = 0; i < length; i++) {                                 if (Yg._.has(columns[i], 'columns') && columns[i].columns.length > 0) {                                     childColumns = childColumns.concat(columns[i].columns);                                 }                             }                             if (childColumns.length > 0) {                                 return this.colDepth(childColumns, len +length-1);                             }                             return len + length;                         }                         FTHead.prototype.addRow = function (columns) {                             var tr = $('<tr>'), childColumns = [], that = this, rowSpan = this.rowDepth(columns,1);                             Yg.each(columns, function (column) {                                 that.addCell(tr, column, rowSpan);                                 if (Yg._.has(column, 'columns'))                                 {                                     childColumns = childColumns.concat(column.columns);                                 }                             });                             this.element.append(tr);                             if(childColumns.length>0)                             {                                 this.addRow(childColumns);                             }                         }                         FTHead.prototype.addCell = function (parent, column, rowSpan) {                             var cell = $('<th>'), crowSpan = 0, attrs = {};                             if (Yg._.has(column, "headFormat"))                             {                                 var template = Yg._.isFunction(column.headFormat) ? column.headFormat : Yg._.template(column.headFormat)                                 cell.html(template(column));                             } else {                                 cell.text(column.title);                             }                             if (Yg._.has(column, "headAttrs")) {                                 attrs = Yg.extend(attrs, column.headAttrs);                             }                             if (Yg._.has(column, 'columns') && column.columns.length>0)                             {                                 attrs.colspan = this.colDepth(column.columns, 0);                                 crowSpan = this.rowDepth(column.columns, 1)                             }                             if (this.visibleNoFixed && !column.fixed) {                                 cell.addClass('fx-hidden');                             }                             rowSpan -= crowSpan;                             if (rowSpan > 1)                             {                                 attrs.rowspan = rowSpan;                             }                             cell.attr(attrs);                             parent.append(cell);                         }                         FTHead.prototype.render = function (parent)                         {                             parent.append(this.element);                         }                         function concatColumn(unionColumns)                         {                             var column, columns=[];                             for (var i = 0, len = unionColumns.length; i < len; i++) {                                 column = unionColumns[i];                                 if (Yg._.has(column, 'columns')) {                                    Yg.each(column.columns,function(c){                                         c.fixed=column.field;                                     });                                    columns.push.apply(columns,concatColumn(column.columns));                                 } else {                                     columns.push(column);                                 }                             }                             return columns;                         }                         function FTBody(columns, visibleNoFixed)                         {                             Yg.bindAll(this, 'addRow');                             this.visibleNoFixed = visibleNoFixed;                             this.columns = columns;                             this.element = $('<tbody>');                         }                         FTBody.prototype.addRow = function (rowData) {                             var that=this, tr = $('<tr>'), columns=this.columns;                             Yg.each(columns, function (column) {                                 that.addCell(tr, column,rowData);                             });                             this.element.append(tr);                         }                         FTBody.prototype.addCell = function (parent, column, rowData) {                             var cell = $('<td>'), attrs = {};                             if (Yg._.has(column, "format")) {                                 var template = Yg._.isFunction(column.format) ? column.format : Yg._.template(column.format)                                 cell.html(template(rowData, column));                             } else {                                 cell.text(rowData[column.field]);                             }                             if (Yg._.has(column, "attrs")) {                                 attrs = Yg.extend(attrs, column.attrs);                             }                             if (this.visibleNoFixed &&!column.fixed)                             {                                 cell.addClass('fx-hidden');                             }                             cell.attr(attrs);                             if (Yg._.has(column, "rowSpan")) {                                 var rowSpan = column.rowSpan(rowData, column),isNumber=typeof rowSpan=="number";                                 if (isNumber && rowSpan > 1)                                 {                                     cell.attr('rowspan', rowSpan);                                 } else if (isNumber && rowSpan < 0) {                                     return;                                 }                                                                                         }                             parent.append(cell);                         }                         FTBody.prototype.renderData = function (data) {                             data = data || [];                             this.element.empty();                             Yg.each(data, this.addRow);                         }                         FTBody.prototype.render = function (parent)                         {                             parent.append(this.element);                         }                            function getStyleValue(value,defaultValue)                         {                             return value != 'auto' && value != null ?parseInt(value):defaultValue;                         }                         var defaultOptions = {                             columns: [],                             dataSource: null,                             autobind: true,                             width: 'auto',                             height: 'auto'                         };                         var Grid = function (element,options) {                             this.options = $.extend({}, defaultOptions, options);                             this.container = $(element).addClass('fx-table-container');                             this.contentTable = null;                             this.wrapper = $('<div class="fx-table-wrapper"><div class="fx-head"></div><div class="fx-body"></div></div>').appendTo(this.container);                             this.initViewSize();                             this.init();                         }                         Grid.prototype.initViewSize = function () {                             var viewWidth = this.container.width(), options = this.options;                                    this._width = getStyleValue(options.width, 0);                             this._height = getStyleValue(options.height, 0);                             this.isScroll = this._width > 0 || this._height > 0;                             this.viewWidth = viewWidth;                             if (this._width > 0) {                                 this.container.css({                                     width: this._width                                 });                             }                         }                                               Grid.prototype.init=function()                         {                             var options = this.options;                             Yg.bindAll(this, '_successHandler','_failHandler');                             this.dataSource = Yg.parseDataSource(this.options.dataSource);                             this.dataSource.then(this._successHandler, this._failHandler);                             this.render();                             if (options.autobind) {                                 this.dataSource.read();                             }                         }                         Grid.prototype._successHandler=function(data)                         {                             this.contentTable.renderData(data);                         }                         Grid.prototype._failHandler = function () {                         }                         Grid.prototype.initTable= function () {                             this.contentTable = new FTable(this.options.columns);                             this.isFixedColumn = this.contentTable.getFixedColumns().length > 0;                         }                         Grid.prototype.initBody = function () {                                                     }                         Grid.prototype._setHeadStyle=function(element)                         {                             element.addClass('fx-head-table fx-hidden-scroll');                         }                         Grid.prototype._setBodyStyle = function (element) {                             element.addClass('fx-body-table fx-body-scroll');                         }                         Grid.prototype._setFixedHeadStyle = function (element) {                             element.addClass('fx-head-table fx-head-fixed fx-hidden-scroll');                         }                         Grid.prototype._setFixedBodyStyle = function (element) {                             element.addClass('fx-body-table fx-hidden-scroll fx-body-fixed');                         }                                                Grid.prototype.initFixedTable=function()                         {                             var that = this, options = that.options,                                 viewWidth=that.viewWidth,                                 width = that._width,                                 height = that._height,                                 contentTable = that.contentTable, isFixedColumn = that.isFixedColumn,                                 elFxHead = that.wrapper.children('.fx-head'),                                 elFxBody = that.wrapper.children('.fx-body'),                                  fHead = contentTable.clone(),                                      fixedBody, fixedHead, isScrollY = false, isScrollX=false;                                                                 fHead.wrapper.addClass('fx-head-table fx-hidden-scroll');                             contentTable.wrapper.addClass('fx-body-table fx-body-scroll');                             //获取表格宽度                             var tableWidth = contentTable.getColumnWidth(width);                             var fixedWidth = contentTable.getFixedColumnWidth(width);                             function setTableLayout()                             {                                                                if (width > 0) {                                                     // 设置固定宽度                                             fHead.setWidth(tableWidth);                                     fHead.setOuterWidth(width);                                     contentTable.setWidth(tableWidth);                                     contentTable.setOuterWidth(width);                                 }                                 if (height > 0&&width>0 && isScrollY)                                 {                                     fHead.setOuterWidth(width-17);                                     contentTable.setOuterHeight(height);                                 } else if (height > 0 && isScrollY) {                                     fHead.wrapper.css("marginRight",'17px');                                     contentTable.setOuterHeight(height);                                 }                                                    if(isFixedColumn)                                 {                                     fixedHead.setOuterWidth(fixedWidth);                                     fixedHead.setWidth(tableWidth);                                     fixedBody.setOuterWidth(fixedWidth);                                     fixedBody.setWidth(tableWidth);                                     contentTable.wrapper.css({                                         width: (width - fixedWidth) + 'px',                                         marginLeft: fixedWidth+'px'                                     });                                     contentTable.element.css({                                         marginLeft: (-fixedWidth) + 'px'                                     });                                 }                                 if (isFixedColumn && height > 0 && isScrollX) {                                     fixedBody.setOuterHeight(height-17);                                 }                                                       }                             if (isFixedColumn) {                                 fixedHead = contentTable.clone();                                 fixedHead.initHead(true);                                 fixedBody = contentTable.clone();                                 fixedBody.initBody(true);                                 fixedHead.render(elFxHead);                                 fixedBody.render(elFxBody);                                 fixedHead.wrapper.addClass('fx-head-table fx-head-fixed fx-hidden-scroll');                                 fixedBody.wrapper.addClass('fx-body-table fx-hidden-scroll fx-body-fixed');                             }                        //     setTableLayout();                             // 初始化                             contentTable.initBody();                             fHead.initHead();                             // 渲染                             fHead.render(elFxHead);                             contentTable.render(elFxBody);                                        contentTable.on('onRenderData', function (data) {                                 if (isFixedColumn)                                 {                                     fixedBody.renderData(data);                                 }                                 // 设置 布局                                 isScrollX = contentTable.wrapper[0].scrollWidth > width                                 isScrollY = contentTable.wrapper[0].scrollHeight > height                                 setTableLayout();                             });                             contentTable.wrapper.on('scroll', function () {                                          fHead&&(fHead.wrapper[0].scrollLeft = this.scrollLeft);                                 fixedBody && (fixedBody.wrapper[0].scrollTop = this.scrollTop);                             });                         }                                                                   Grid.prototype.render=function()                         {                             var that = this;                             this.initTable();                             if (this.isFixedColumn || this.isScroll) {                                 this.initFixedTable();                             } else {                                 this.contentTable.initHead();                                 this.contentTable.initBody();                                 this.contentTable.render({                                     append: function (child) {                                         that.wrapper.html(child);                                     }                                 });                             }                         }                                                                          new Grid('#grid', {                             dataSource: {                                 data: [{                                     name: "李三",                                     rowspan:3,                                     age: 43,                                     work: '北京',                                     work2: '上海'                                 }, {                                     name: "",                                     rowspan:-1,                                     age: 43,                                     work: '北京',                                     work2: '上海'                                 }, {                                     name: "",                                     rowspan:-1,                                     age: 43,                                     work: '北京',                                     work2: '上海'                                 }, {                                     name: "李四",                                     age: 43,                                     work: '北京',                                     work2: '上海'                                 }, {                                     name: "李三",                                     age: 43,                                     work: '北京',                                     work2: '上海'                                 }, {                                     name: "李四",                                     age: 43,                                     work: '北京',                                     work2: '上海'                                 }, {                                     name: "李三",                                     age: 43,                                     work: '北京',                                     work2: '上海'                                 }, {                                     name: "李四",                                     age: 43,                                     work: '北京',                                     work2: '上海'                                 }, {                                     name: "李三",                                     age: 43,                                     work: '北京',                                     work2: '上海'                                 }, {                                     name: "李四",                                     age: 43,                                     work: '北京',                                     work2: '上海'                                 }, {                                     name: "李三",                                     age: 43,                                     work: '北京',                                     work2: '上海'                                 }, {                                     name: "李四",                                     age: 43,                                     work: '北京',                                     work2: '上海'                                 }]                             },                            width:700,                            height:150,                             columns: [                                 {                                     title: '姓名',                                     field: 'name',                                     fixed: true,                                     width: '200px',                                     headAttrs: {                                         style: 'text-align:center'                                     },                                     rowSpan:function(row,c)                                     {                                         return row.rowspan;                                     }                                 },                                  {                                      title: '年龄',                                      field: 'age',                                      width: 100,                                   //   fixed: ,                                      headAttrs: {                                          style: 'text-align:center'                                      }                                  }                                  ,                                  {                                      title: '工作经历',                                      headAttrs: {                                          style: 'text-align:center'                                      },                                      columns: [                                                  {                                              title: '工作经历2',                                              headAttrs: {                                                  style: 'text-align:center'                                              },                                              columns: [                                        {                                            title: '工作经历2',                                            field: 'work',                                            width: 100,                                        }, {                                            title: '工作经历5',                                            field: 'work2',                                            width: 200,                                        }]                                          }, {                                              title: '工作经历5',                                              field: 'work2',                                              width: 300,                                          }                                      ]                                  },                                   {                                       title: '呵呵',                                       field: 'age',                                       headAttrs: {                                           style: 'text-align:center'                                       },                                       width: 100,                                   }                             ]                         });                     }());                     //$('#scrollBody').on('scroll', function () {                     //    $('#scrollHead')[0].scrollLeft = this.scrollLeft;                     //    $('#scrollBodyY')[0].scrollTop = this.scrollTop;                     //});                 });

转载请注明原文地址: https://www.6miu.com/read-32016.html

最新回复(0)