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

前段时间一个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>

锁定表头固定左边列,原生JS原创代码 需要注意的问题: 1.表格的宽度以及表格每一列的宽度需要固定(特殊情况除外:当表格列数少并且表格总宽度明显小于表格父容器的宽度时,也就是表格列不存在自动换行的问题) 2.表格父容器尺寸大小改变时,需要调用 setBoxSize 方法,目的是判断父容器是否出现滚动条 1.1 修正了对IE6、IE7的兼容问题 1.2 修正了固定行、列的样式问题 1.3 IE6/IE7浏览器 不启用该功能 1.4 增加了拆分线, 修正了重复生成锁定行列的问题以及生成错位的问题, 修正了行、列事件无法复制的问题, 增加了IE6/IE7/IE8 启用设置参数(ieLowVersionEnabled: true|false) ,默认不启用, 注:IE6/7/8锁定表头 由于兼容性问题,有些情况下会有一些错位的问题 1.5 增加了 显示/隐藏功能,修正了非IE浏览器下列宽错位问题 1.6 修正了当有合并单元格时,锁定单元格错位的问题,修正了表格行数较多时的性能问题 1.7 表格单元格可以不指定宽度(锁定时,取实际的单元格宽度),当单元格的左右两边的borderWidth不一样时,会有一些错位 若单元格宽度是固定的,可以在第3个参数(config)中指定 isFixedSize:true 修正表头列未锁定的Bug 1.8 修正表格含有thead时的样式丢失问题,以及行数设置问题,修正thead/tbody行归属问题 1.9 移除tbTopLeft的边框线 修正表格cellpadding/cellspacing的设置问题 修复Firefox下的padding导致的错位问题 修复thead复制没有底部分割线的问题 修复thead复制时无背景色的问题 增加复选框同步功能(如果是JS代码设置复选框选中,需要调用 .setCheckBoxSync()方法) .setCheckBoxSync 方法参数说明:4种参数 1) 复选框控件(html object)数组 2) 复选框控件(html object) 3) 复选框控件ID (string) 4) 空参数(尽量不用空参数)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值