# 冻结HTML Table,固定表格特定行列,固定行首列首

当表格行列数较多时，为了用户在屏幕内容滚动时更加方便的查看数据，我们期望可以像Excel一样冻结表格的固定行和列（一般为表头和列头），遗憾的是HTML中并没有这种效果，那让我们来动手开发吧，Let’s do it！

实现表格行列冻结效果，网上较多采用以下两种方式：

*  通过多个表格拼接层叠，Js控制多个表格间的联动。这种方式逻辑简单，容易实现，但代码冗余，难以维护，灵活性不好，适合简单场景下使用。
*  通过创建多个div，div之间通过css实现层叠，每个div放置当前表格的克隆。例如：需要行冻结时，创建存放冻结行表格的div，通过设置z-index属性和position属性，让冻结行表格在数据表格的上层。同理，需要列冻结时，创建存放冻结列表格的div，并放置在数据表格的上层。如果需要行列都冻结时，则除了创建冻结行、冻结列表格的div，还需要创建左上角的固定行列表格的div，并放置在所有div的最上层。 这种方式与第一种思路类似，只是实现冻结部分是动态创建，这种方式可维护性比第一种略好。

## 1. 表格层叠
### 1.1 冻结某一行(列)
(1) 把看起来是一个整体的表格拆分成两部分，table1负责固定部分如thead，而table2负责可以拖动的部分如tbody


![冻结行/列](https://cdn.hashnode.com/res/hashnode/image/upload/v1658686095243/lsyCYG0sh.jpg align="left")

```html
<div class="table-out">
    <div class="table-top">
        <table>
            <thead>
                <tr><th>姓名</th><th>学号</th><th>年龄</th></tr>
            </thead>
        </table>
    </div>
    <div class="table-main">
        <table>
            <tbody>
                <tr><td>张三</td><td>001</td><td>17</td></tr> 
                <tr><td>李四</td><td>002</td><td>18</td></tr> 
            </tbody>     
        </table>                
    </div>
</div>
```

(2) 把两个table固定好了之后，监听table2的滚动，用table2的滚动带动table1的滚动（通过设置css里的left 或者 scroll，如果是绝对定位那么只能用设定css中left的方法）
```javascript
$('.table-main').scroll(function() {
    var scrollLeft = $(this).scrollLeft();
    $('.table-top').scrollLeft(scrollLeft);
});
```
### 1.2 同时冻结行和列
(1) 把看起来是一个整体的表格拆分成四个部分

![冻结行列](https://cdn.hashnode.com/res/hashnode/image/upload/v1658686317477/P4xC5l5jd.jpg align="left")

```html
<div class="table-out">
    <!--固定行-->
    <div class="table-top">
        <table>
            <thead>
                <tr>
                    <th>零件名称</th>
                    <th>换件日期</th>
                    <th>寿命比例</th>
                </tr>
            </thead>
        </table>
    </div>
    <!--内容-->
    <div class="table-main">
        <table>
            <tbody>
                <tr>
                    <td>电机</td>
                    <td>2015-08-25</td>
                    <td>
                        <progress value="0.6"></progress>
                    </td>
                </tr>
                <tr>
                    <td>蝶型弹簧</td>
                    <td>2015-08-25</td>
                    <td>
                        <progress value="0.4"></progress>
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
    <!--固定列-->
    <div class="table-left">
        <table>
            <tbody>
                <tr><td>电机</td></tr>
                <tr><td>蝶型弹簧</td></tr>
            </tbody>
        </table>
    </div>
    <!--左上角交叉区-->
    <div class="table-left-top">
        <table>
            <thead>
                <tr>
                    <th>备件名称</th>
                </tr>
            </thead>
        </table>
    </div>
</div>
```

(2) 把四个table固定好了之后，监听table-main的滚动，用table-main的滚动带动table-top的左右移动和table-left的上下移动。在这个示例里，我对table-left用到了绝对定位，所以给table-left设定scroll无效，但是可以使用改变table-left的css中top的属性值来使得table-left上下移动

```javascript
var tb=$('.table-out');
var tbLeft=tb.children('.table-left');
var tbTop=tb.children('.table-top');
var tbMain=tb.children('.table-main');

var leftTop = parseInt(tbLeft.css('top'));
tbMain.scroll(function() {		
    tbLeft.css('top',leftTop - tbMain.scrollTop()+'px');
    tbTop.scrollLeft(tbMain.scrollLeft());
});
```
## 2. SuperTable(动态创建表格)

手动拼接表格的方式会在Html中存在较多冗余代码，表格结构维护起来比较繁琐，我们可以通过js读取html中表格结构然后动态创建div或table来完成层叠拼接工作，这样一来我们可以简单的在html中维护一份table的干净代码即可。

原理与前面相同，代码比较简单，这里我们不再赘述。

![动态创建表格.gif](https://cdn.hashnode.com/res/hashnode/image/upload/v1658686519622/AwNsq2kJa.gif align="left")

