vue实现表格表头在左侧,并且固定表头

前段时间一个h5端的项目,需要实现一个表格,然后表格的表头放在左侧一列,并且左右滚动的时候需要固定表头,不能随着滚动条滚动一起动。

效果图如下:

因为我这个项目的框架是ant design vue,想过用组件里的表格,但是看了下,用表格组件还不如自己写一个,又快又省事很多。但是在网上找了很多类似的,思路是可以的,就是没有一个是我能运行起来的,最后就决定自己写一个。

实现思路:

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>

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值