前段时间一个h5端的项目,需要实现一个表格,然后表格的表头放在左侧一列,并且左右滚动的时候需要固定表头,不能随着滚动条滚动一起动。
效果图如下:
实现思路:
1、首先先用div实现表格的样子,类名table-box使用position: relative;相对定位,然后header-title表头使用position: absolute,在给具体宽高;
2、之后在写一个表头作用于固定列,使用position: sticky;top:0;left:0吸顶属性固定在表格最左侧;之后使用z-index: 9999;把固定表头堆叠在最上面。
3、最后就是处理数据了,先确定表头的字段columns,然后使用forEach循环columns,把数据this.data通过方法放进columns里的item.values数组里,最后循环渲染出来就可以了。
<template>
<div>
<div v-if="data.length > 0" class="table-box">
<!-- 固定列 表头 -->
<div class="fixed-columns fixed-backgound1">
<div v-for="(item) in columns" :key="item.title">
<div>{{ item.title }}</div>
</div>
</div>
<!-- 原本的表格+数据 -->
<div class="value-box">
<div v-for="(item,index) in columns" :key="index">
<!-- 表头 -->
<div class="content-box">
<div class="header-title header-title-backgound1">
<div class="name">{{ item.title }}</div>
</div>
<!-- 数据 -->
<div class="value-text" v-for="(item2,index2) in item.value" :key="index2">
{{ item2 }}
</div>
</div>
</div>
</div>
</div>
<van-empty v-else description="暂无数据" />
</div>
</template>
<script>
export default {
data () {
return {
columns: [],
data: []
}
},
methods: {
init () {
this.columns = [{
title: '新区域',
dataIndex: 'qy'
}, {
title: '大区',
dataIndex: 'dq'
}, {
title: '季度净利润区间开始',
dataIndex: 'profit_bonus_start'
}, {
title: '开始是否含',
dataIndex: 'contain_start'
}, {
title: '季度净利润区间结束',
dataIndex: 'profit_bonus_end'
}, {
title: '结束是否含',
dataIndex: 'contain_end'
}, {
title: '该区间季度利润绩效',
dataIndex: 'profit_bonus_commission'
}]
this.data = [
{
'id': 1,
'dq': '一大区',
'qy': '区域一',
'profit_bonus_start': '10',
'contain_start': '是',
'profit_bonus_end': '200',
'contain_end': '否',
'profit_bonus_commission': '600'
},
{
'id': 2,
'dq': '二大区',
'qy': '区域二',
'profit_bonus_start': '200',
'contain_start': '是',
'profit_bonus_end': '500',
'contain_end': '否',
'profit_bonus_commission': '100'
},
{
'id': 3,
'dq': '三大区',
'qy': '区域三',
'profit_bonus_start': '300',
'contain_start': '是',
'profit_bonus_end': '500',
'contain_end': '否',
'profit_bonus_commission': '100'
},
{
'id': 4,
'dq': '四大区',
'qy': '区域四',
'profit_bonus_start': '400',
'contain_start': '是',
'profit_bonus_end': '500',
'contain_end': '否',
'profit_bonus_commission': '100'
}
]
//处理数据,把处理好的数据放进表头数组里
this.columns.forEach(item => {
item.value = []
for (const i in this.data) {
for (const j in this.data[i]) {
if (item.dataIndex === j) {
item.value.push(this.data[i][j])
}
}
}
})
}
},
mounted () {
this.init()
}
}
</script>
<style lang="less" scoped>
.fixed-columns {
width: 105px;
position: sticky;
z-index: 9999;
top: 0;
left: 0;
>div {
height: 50px;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
color: #333333;
font-size: 12px;
font-weight: 500;
border-bottom: 1px solid #E1E1E1;
border-right: 1px solid #E1E1E1;
border-left: 1px solid #E1E1E1;
}
}
// 固定的表头背景颜色
.fixed-backgound1 {
background-color: #FDF9EE;
}
.fixed-backgound2 {
background-color: #FFF3F3;
}
.value-box {
/*-350px是所有表头加起来的高度,用于固定表头 */
margin-top: -350px;
}
.table-box {
width: 100%;
border-radius: 4px;
border-top: 1px solid #E1E1E1;
overflow-x: auto;
position: relative;
font-family: PingFangSC, PingFang SC;
.content-box {
width: 100%;
height: 50px;
display: flex;
.header-title {
width: 105px;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
border-bottom: 1px solid #E1E1E1;
border-right: 1px solid #E1E1E1;
border-left: 1px solid #E1E1E1;
color: #333333;
font-size: 12px;
font-weight: 500;
position: absolute;/*表头固定 */
left: 0;
z-index: 999;
}
.name {
text-align: center;
}
.value-text {
min-width: 80px;
display: flex;
align-items: center;
justify-content: center;
border-bottom: 1px solid #E1E1E1;
border-right: 1px solid #E1E1E1;
text-align: center;
font-size: 12px;
}
.value-text:nth-child(2) {
/*表头固定后,数据内容的第一列需要设置左边距空出表头的宽度*/
margin-left: 105px;
}
// 根据需要改变表头的背景颜色
.header-title-backgound1 {
background-color: #FDF9EE;
}
.header-title-backgound2 {
background-color: #FFF3F3;
}
}
}
</style>