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

2023-11-08

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

支持自适应页面宽度和可以设置固定宽度,理论上是所有浏览器都支持,但是因为我引用了一些工具类,处理数组的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;
                    //});
                });

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

复杂grid 支持多表头,固定表头,冻结列,合并行 的相关文章

随机推荐

  • socks协议解析

    SOCKS5 协议解析 一 定义 SOCKS5 是一个代理协议 旨在为位于 Intranet 防火墙后的用户提供访问 Internet 的代理服务 有些博文说Socks协议位于7层协议的传输层 有些博文说位于会话层 我个人的理解是位于会话层
  • 【JavaScript】数组去重

    数组去重 1 Set console log Array from new Set arr console log new Set arr 2 indexOf function unique var newArr for var i 0 i
  • Pytest 自定义HOOK函数

    除了系统提过的HOOK函数外 也可以通过自定义HOOK的方式实现想要的功能 首先创建一个py文件 里面定义自己的HOOK函数 主要pytest里面的hook函数必须以pytest开头 myhook py def pytest myhook
  • 三. Zuul 网关服务基础解释及基础搭建测试

    目录 一 基础 Zuul 与 Gateway 区别 二 Zuul1 网关 三 Zuul 核心过滤器 pre过滤器 route过滤器 post过滤器 四 搭建 Zuul 网关服务 通过 Zuul 间接访问微服务接口 1 步骤 2 创建目标服务
  • 女性架构师优先?驾驭概念的技能是最高潜力

    51CTO独家特稿 在近日51CTO开发频道对数位架构师进行采访的时候 编辑观察到一个很有意思的现象 那就是他们在提起一个假想架构师的时候会下意识的使用 she 或者 她 来指代 然而我们这次采访到的的架构师们却全都是男士 这似乎是一个比较
  • 1254 统计封闭岛屿的数目(dfs)

    1 问题描述 有一个二维矩阵 grid 每个位置要么是陆地 记号为 0 要么是水域 记号为 1 我们从一块陆地出发 每次可以往上下左右 4 个方向相邻区域走 能走到的所有陆地区域 我们将其称为一座 岛屿 如果一座岛屿 完全 由水域包围 即陆
  • AJAX异步请求&JSON数据格式

    目录 前言 1 AJAX的实现方式 1 1原生的js实现方式 1 2JQuery实现方式 2 1语法 3 JSON数据和Java对象的相互转换 3 1将JSON转换为Java对象 3 2将Java对象转换为JSON 前言 AJAX ASyn
  • 重启虚拟机后dhclient进程未运行解决办法

    https www cnblogs com jiawei2527 p 10778938 html 问题分析 重启虚拟机后 dhclient进程未运行的根因通常为 1 NetworkManager未开启自启动导致的dhclient进程未运行
  • 计算机组成原理--基于Logisim的奇偶校验电路实验的应用(超详细/设计/实验/作业/练习)

    目录 课程名 计算机组成原理 内容 作用 设计 实验 作业 练习 学习 基于Logisim的奇偶校验电路实验 一 前言 二 环境与设备 三 内容 四 结果与分析 课程名 计算机组成原理 内容 作用 设计 实验 作业 练习 学习 基于Logi
  • 实现整数堆栈算法的Java程序

    实现整数堆栈算法的Java程序 堆栈 Stack 是一种常用的数据结构 它遵循先进后出 Last In First Out LIFO 的原则 在Java中 我们可以使用整数堆栈算法来实现一个基本的堆栈数据结构 本文将演示如何使用Java编写
  • vue 图片下载到本地,图片保存到本地

    必须同源 访问的网站域名与服务器域名一致 才能下载 downs var alink document createElement a alink href this shop shoppic url alink download pic 图
  • 没有libelf.h libdw.h

    执行如下安装 apt get install libdw dev
  • editview只输入英文_android使用正则表达式控制EditText只能输入数字和英文

    在方法中加载 edt addTextChangedListener new SearchWather edt 新建类 SearchWather java import java util regex Matcher import java
  • 企业微信获取用户信息响应40029(微信小程序与公众号出现类似问题应该是同样的原因)

    企业微信获取用户信息响应40029 在对接企业微信的时候需要通过code去获取userId 但是会返回40029的error码 经过测试与验证原因是访问地址 https open weixin qq com connect oauth2 a
  • 【Vue学习笔记】export ‘default‘ (imported as ‘Vue‘) was not found in ‘vue‘问题解决

    export default imported as Vue was not found in vue 安装了5 几的vuecli src plugins element js里用到了 import Vue from vue npm run
  • 绝无仅有的SpringBoot+Vue前后端分离项目《盈利宝》

    每天都在制造矛盾并解决矛盾的路上 程序员的主要矛盾 不是书和资料多不多的矛盾 而是学着学着发现知识又更新了 时间就像一台永不停歇的永动机 向前不停地运作 年初的flag渐行渐远 管他前浪 还是后浪 能浪的浪 才是好浪 今天带你解锁 Spri
  • gitlab操作

    1 配置ssh 点击访问 2 创建新分支与切换新分支 git branch 新分支名 创建 git checkout 新分支名 切换到新分支 3 查看当前分支 git branch 所指的就是当前所在分支 4 本地删除文件后与远程git同步
  • JConsole&VisualVM监控总结

    简介 JConsole 以下写作jconsole VisualVM 以下写作jvisualvm 都是比较好的JVM调优工具 且都为JDK自带 可在命令行直接启动 监控示例 Server端 需要监控的主机 配置 设置临时JAVA参数 expo
  • 管理用户账号

    目录 Windows平台用户账号介绍 管理本地用户账号 用户配置文件 演示配置漫游用户配置文件 强制漫游配置说明 管理本地组 组的操作 案例分析 Windows平台用户账号介绍 在Windows系统中 每当用户需要登录到系统时就需要对用户进
  • 复杂grid 支持多表头,固定表头,冻结列,合并行

    该组件支持三种渲染形态 因为有些简单的表格没必要去做太复杂的处理 支持自适应页面宽度和可以设置固定宽度 理论上是所有浏览器都支持 但是因为我引用了一些工具类 处理数组的filter map 所以向前兼容可以自己实现这些方法 第一种 不需要固