公司有了新的需求,就是需要一个头部固定的表格,查来查去,都觉得很麻烦,干脆自己写一个好了
如第一幅图所示,效果很好,由于宽度是由浏览器窗口变化的时候通过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里面设置就行。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。