公司有了新的需要,就是须要一个头部固定的表格,查来查去,都感觉很麻烦,罗唆本人写一个好了
如第一幅图所示,成果很好,因为宽度是由浏览器窗口变动的时候通过 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
设置为 tabHead
中width
的值。
<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
设置为 tabHead
中width
的值。不过外层加了一层 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;
}
简而言之就是 tabHead
的property
会对应 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 外面设置就行。