公司有了新的需要,就是须要一个头部固定的表格,查来查去,都感觉很麻烦,罗唆本人写一个好了

如第一幅图所示,成果很好,因为宽度是由浏览器窗口变动的时候通过js计算取得,css仅仅只是设置局部的最小宽度,所以兼容性必定是没有任何问题的。


首先要明确的就是,既然头部须要固定,那么头部和身材必定是分成两个表格来做的,构造如下

<div> <div class="table1">  <table></table> </div> <div class="table2">  <table></table> </div></div>

而后问题来了,因为是两个table,那么他们的td的宽度是由各自的内容决定的,天然宽度在不通过人为操纵的状况是相对不可能一样的。既然如此,那通过同一个对象治理两个表格,那么宽度天然就雷同了。

先看ts代码内容

  tabHead: Array<any> = [    { title: '操作', property: 'checkbox', type: 'checkbox', width: '' },    { title: '序号', property: 'serial', type: 'serial', width: '' },    { title: '信息类型', property: 'infoType', type: 'special', children: 'infoTypeChildren', param: 'infoTypeCode', width: '', fackItem: 'a' },    { title: '服务名称', property: 'serviceName', type: 'special', children: 'serviceChildren', param: 'serviceId', width: '', fackItem: 'b' },    { title: "数据起源", property: 'sourceName', type: 'special', children: 'sourceChildren', param: 'dataSourceId', width: '', fackItem: 'c' },    { title: "服务版本", property: 'serviceVersion', width: '' },    { title: "服务形容", property: 'description', width: '' },    { title: "注册单位", property: 'register', width: '' },    { title: "注册工夫", property: 'registerDate', width: '' },    { title: "服务状态", property: 'status', type: 'state', width: '' },  ]

下面的是两个table共用的对象,其余的字段能够不必理,只须要看title property width三个字段就行

再看html代码内容

    <div class="table1">      <table class="service-table" >        <tr class="head">          <ng-container *ngFor="let item of tabHead">            <td [ngStyle]="{'width':item.width}" class="{{item.property}}">              {{item.title}}            </td>          </ng-container>        </tr>      </table>    </div>

这个是头部表格的简化后的代码,利用angular的*ngFor属性,遍历tabHead循环出td并且给td的款式width设置为tabHeadwidth的值。

      <div class="table2" >        <table class="service-table">            <tr *ngFor="let data of tabData;let i = index" #element>              <ng-container *ngFor="let item of tabHead">                 <td [ngStyle]="{'width':item.width}" class="{{item.property}}">                   <span [class]="item.class" [style]="item.style" [innerHTML]="data[item.property]?data[item.property]:'--'"                        [title]="data[item.property]?data[item.property]:'--'"></span>                   </td>              </ng-container>            </tr>        </table>      </div>

同样,这个是身材表格简化后的代码,同样利用angular的*ngFor属性,遍历tabHead循环出td并且给td的款式width设置为tabHeadwidth的值。不过外层加了一层tableData的循环,其字段如下

export class ServiceContentListModel {    dataSourceId?: string;    sourceChildren?:Array<any>;    description?: string;    id?: string;    infoType?: string;    infoTypeCode?: string;    register?: string;    registerDate?: string;    serialNumber?: number;    serviceId?: string;    serviceName?: string;    serviceVersion?: string;    sourceName?: string;    status?: string;    noneed?:boolean=false;}

简而言之就是tabHeadproperty会对应tableData的字段,而后把对应上的显示到页面上。具体不表


这样一番操作,能够想到两张表格中td的宽度都是由同一个对象tableHead中的width属性决定的了,那么接下来只有通过拿到身材表格每一个td的宽度,而后赋值给tabHead就行了。

//因为我应用的是angular,所以以下代码带有angular的个性,当然情理是相通的,用vue甚至用原生js写法略微变通一下//也是能够实现的@ViewChild('element') navListElement: ElementRef;//拿到tr的dom元素 ngAfterViewInit() {//在子元素加载实现后执行    this.setWidth()    window.onresize = ($event) => {//浏览器窗口大小变动当前执行      this.setWidth()    }  }      setWidth() {    setTimeout(() => {//提早一个生命周期后进行,不然在页面渲染实现当前表格还是对不齐状态      if (this.navListElement) {        let children = this.navListElement.nativeElement.children;//拿到一个tr中所有td的汇合        let widthSum = 0//寄存一个tr中所有td的宽度,用于计算每个td所占的百分比        for (let i = 0; i < this.tabHead.length; i++) {//每一列宽度换算成像素宽度(除了最初一列)          let item = children[i]          // this.tabHead[i]['width'] = item.offsetWidth + "px"          widthSum+=item.offsetWidth        }        for (let i = 0; i < this.tabHead.length; i++) {//每一列宽度换算成百分比(除了最初一列)          let item = children[i]          this.tabHead[i]['width'] = (item.offsetWidth/widthSum)*100 + '%'        }      }    });  }

这样就实现了,具体点的工作,比方设置最小宽度之类的,间接在css外面设置就行。