elementUI中的elTable实现原理图

上图是我们使用element table组件的一个常见场景,顶部固定,左侧列固定,右侧列固定,甚至底部行固定。这些特性对于展现数据,报表等是非常友好的一种用户体验。
今天我们不谈elTable的使用,今天我们来谈一谈elTable功能实现的原理。

第一步,我们就需要正常的展现这个table表格,td中的宽度用户设定多少就是多少,没设定就自动宽度。
第二步,通过js操作dom,获取到这个table中,每一行的高度,每一列的宽度。
第三步,实现table功能的的布局。

这样,我们table布局就实现了。简单点实现的话,每一个块内都放置整个table,然后定义定高或者定宽。超出部分不展示。
第四步,滚动条跟随滚动,如果有纵向滚动条,那么添加滚动事件,在滚动时,左侧,右侧固定列偏移对应的滚动值。横向滚动条类似。
第五步,gutter,比如出现纵向滚动条时,内容去的table宽度小了一个滚动条的宽度,那么头部固定表格需要添加一个空td,设置宽度为滚动条宽度,才能与内容区table对齐。计算方法就是内容去table外层div的offsetWidth - clientWidth得到滚动条的宽度。

gutter就是上图红框区域。
综上所述,elementUI的elTable实现原理就是上面这几步骤。
用途
Vue中JSX使用绘制报表,此文章处就是一个使用的地方,对于复杂报表,不管是elementUI table,还是vxe-table都显得无能为力。这时候我们就可以使用更加灵活强大的render函数来实现功能了。
但是如果客户需要表头固定,那么我们就需要用到上面的知识了。

运用上述知识,我们就可以轻松实现表头固定的功能。
export default{
props:{
lists:{
type:Array,
default:()=>{
return [];
}
},
tps:{
type:Array,
default:()=>{
return ['银川','吴忠','石嘴山','中卫','宁东','固原'];
}
},
//前五名加背景色
five:{
type:Boolean,
default:false
}
},
data(){
return {
gutter:0,
}
},
computed:{
dobleList(){
let arr = [];
for(let i =0 ;i
arr.push(this.lists[i]);
arr.push(this.lists[i]);
}
return arr;
}
},
mounted(){
setTimeout(()=>{
this.$nextTick(()=>{
this.calGutter();
});
},500);
},
methods:{
calGutter(){
let cht = this.$refs.cont.clientHeight;
let tht = this.$refs.tbs.offsetHeight;
let owd = this.$refs.cont.offsetWidth;
let cwd = this.$refs.cont.clientWidth;
if(tht<=cht){
this.gutter = 0;
}else{
this.gutter =( owd - cwd -2) + 'px'
}
},
gettClass(it,k){
let cstr = '';
if(it.value&&it.value.length>k){
if(it.value[k].zbpm==1){
cstr = 'rp-first';
} else if (this.five){
switch(it.value[k].zbpm){
case 2:
case 3:
case 4:
case 5: cstr = 'rp-two';
}
}
}
return cstr;
}
},
render(){
return (
{
this.tps.map(it=>{
return
{it}})
}
{
this.gutter!=0?
:""}
{
this.dobleList.map((it,i)=>{
if(i%2==0){
return (
{
i/2==1?
专业管理:""}
{ it.dwmc }得分{
this.tps.map((t,k)=>{
return
{
it.value&&it.value.length>k?it.value[k].zbdf:""
}
})
}
{
this.gutter>0?
:""}
)
}else{
return (
排名{
this.tps.map((t,k)=>{
return
{
it.value&&it.value.length>k?it.value[k].zbpm:""
}
})
}
{
this.gutter!=0?
:""}
)
}
})
}
{
this.tps.map(it=>{
return
{it}})
}
{
this.dobleList.map((it,i)=>{
if(i%2==0){
return (
{
i/2==1?
专业管理:""}
{ it.dwmc }得分{
this.tps.map((t,k)=>{
return
{
it.value&&it.value.length>k?it.value[k].zbdf:""
}
})
}
)
}else{
return (
排名{
this.tps.map((t,k)=>{
return
{
it.value&&it.value.length>k?it.value[k].zbpm:""
}
})
}
)
}
})
}
)
}
}
完整表头固定代码如上,我是采用了第二种方式,表头区域渲染了整个table的备份,只是设置了固定高度截图表头部分。算是偷懒的实现吧。/* 报表样式 */
.rp-header{background:#e1e1e1;}
.rp-table th,.rp-table td{text-align:center;line-height: 28px;font-size:13px;color:#0E0E0E;}
.rp-noscroll{height:29px;overflow:hidden;top:0;left:0;right:0;position:absolute;z-index: 2;}
.rp-table td.rp-first{background:#00A187;color:#fff;font-weight:bolder;}
.rp-table td.rp-two{background:#31E4C7;color:#fff;}
样式只要通过absolute定位就可以实现了。
希望此文章对你能有所帮助。