移动端实现固定表格首列和表头(vue)

移动端实现固定表格首列和表头(vue)

由于移动端项目需求要实现一个能够固定表格首列和表头的表格,可是移动端对表格需求不多,用的组件库中也没有设计这个组件,也不能用插件,因此只能本身写一个。语言是vue。css

基本思想:把首列和表头和主体表格分开;而后给tbody添加一个滑动监听,滑动的时候,触发事件让表头和首列固定就能够。html

可是注意的是,高度和宽度必须都要统一设置好,否则会出现表格不对齐的问题。vue

实现效果:
在这里插入图片描述web

代码实现:(vue主体部分)svg

<template>
  <div 
    ref="pages" 
    class="pages"
  >
    <div 
      ref="table" 
      class="content1"
    >
      <!--首列固定-->
      <div class="left-content">
        <div class="table-head">
          <table class="full-table">
            <thead>
              <tr 
                v-for="(header,index) in tableHeader" 
                :key="index"
              >
                <th 
                  v-for="(b,x) in header" 
                  v-show="x===0"
                  :key="x"
                >
                  <p>
                    {{ b }}
                  </p>
                </th>
              </tr>
            </thead>
          </table>
        </div>
        <div class="table-left">
          <div 
            ref="firstColLayer" 
            class="table" 
            data-_ref="firstColLayer"
          >
            <table class="full-table">
              <tbody>
                <tr 
                  v-for="(row,index) in dataSheet" 
                  :key="index"
                >
                  <td 
                    v-for="(c,y) in row"  
                    v-show="y===0"
                    :key="y"
                  >
                    <p>{{ c }}</p>
                  </td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
      </div>
      <div 
        ref="right" 
        class="right-content"
      >
        <!--首行固定-->
        <div 
          ref="firstRowLayer" 
          class="table-head" 
          data-_ref="firstRowLayer"
        >
          <table>
            <thead>
              <tr 
                v-for="(header,index) in tableHeader" 
                :key="index"
              >
                <th 
                  v-for="(b,n) in header" 
                  v-show="n!==0" 
                  :key="n"
                >
                  <p>
                    {{ b }}
                  </p>
                </th>
              </tr>
            </thead>
          </table>
        </div>
        <!--正常表格内容(只有表格内容,没有表头和首列)-->
        <div
          ref="tableContainer"
          class="table"
          style="overflow:scroll"
          @scroll="tableDivScroll($event)"
        >
          <table>
            <tbody ref="tbody">
              <tr 
                v-for="(row,index) in dataSheet" 
                :key="index"
              >
                <td 
                  v-for="(c,m) in row" 
                  v-show="m!==0" 
                  :key="m"
                >
                  <p>{{ c }}</p>
                </td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  name: "Table",
  data() {
    return {
      dataSheet: [
        [
          "承订人", "2222222", "123", "444444", "20%", "20%",
        ],
        [
          "111", "2222222", "123", "444444","20%", "20%",
        ],
        [
          "111", "2222222", "123", "444444","20%", "20%",
        ],
        [
          "111", "2222222", "123", "444444","20%", "20%",
        ],
        [
          "111", "2222222", "123", "444444","20%", "20%",
        ],
        [
          "111", "2222222", "圣", "444444","20%", "20%",
        ],
        [
          "111", "2222222", "圣卡夫2", "444444","20%", "20%",
        ],
        [
          "111", "2222222", "123", "444444","20%", "20%",
        ],
        [
          "111", "2222222", "123", "444444","20%", "20%",
        ],
        [
          "111", "2222222", "123", "444444","20%", "20%",
        ],
        [
          "111", "2222222", "3333333", "444444","20%", "20%",
        ],
        [
          "111", "2222222", "333", "444444","20%", "20%",
        ],
        [
          "111", "2222222", "123", "444444","20%", "20%",
        ],
        [
          "111", "2222222", "123", "444444","20%", "20%",
        ],
        [
          "111", "2222222", "123", "444444","20%", "20%",
        ],
      ],
      tableHeader: [
        [ 
          "人员代码","派工件数","预算金额","实际金额","当月达成率","整年达成率",
        ],
      ],
    };
  },
  mounted() {
    // 定一个生命周期钩子监听变更
    // let maxHeight = window.screen.height
    document.body.style.overflow = "hidden";
    // this.$refs.right.style.width =
    //   "" + this.$refs.table.offsetWidth - 12 + "px"; // 这里的减101是减去左侧div宽度
    // console.log(this.$refs.right.style.width);
  },
  activated: function() {},
  methods: {
    tableDivScroll() {
      const $target = this.$refs.tableContainer;
      // 首行固定
      this.$refs.firstRowLayer.scrollLeft = $target.scrollLeft;
      // 首列固定
      this.$refs.firstColLayer.scrollTop = $target.scrollTop;
    },
  },
};
</script>

css样式:this

<style scoped>
/* 表格分为两部分,左边固定列和右边表格 左边固定列宽度为60px;右边为70px,右边由于要加边框 因此就是68+2px(左右边框) */
body {
  overflow: hidden;
}
table::-webkit-scrollbar {
  display: none;
}
thead, tbody {
  overflow: hidden;
  background-color: #ffffff;
}
th, td p {
  width: 68px;
  height: 40px;
  display: inline-block;
  line-height: 20px;
  padding: auto 0;
  margin: auto 0;
  vertical-align: middle;
  white-space:normal;
}
tr {
  height: 40px;
}
th {
  background-color: #cbcdc8;
}
td{
  border: 1px solid
}
.pages {
  height: 100%;
  overflow: hidden;
}
.content1 {
  height: 450px;
  overflow: hidden;
  margin: 5px;
}
/* 固定列的宽度为60 */
.left-content {
  width: 60px;
  float: left;
  text-align: center;
  border-top: 1px solid
}
.left-content p{
  width: 60px;
  height: 40px;
  word-wrap: break-word;
}
.right-content{
  border-top: 1px solid
}
/* 去掉表格的重复边框 */
.full-table{
  border: 0px;
  border-collapse: collapse;
}
.table-body {
  width: 100%;
  overflow: auto;
}
.table {
  height: 450px;
  overflow: auto;
}
/* 表头 */
.table-head {
  overflow: hidden;
  white-space: nowrap;
}
.table-head th{
  width: 69px;
  border-left: 1px solid;
}
</style>

说明:功能是实现了,代码里面也有注释,可是兼容性作的还不是很好,但愿大佬们给出建议和帮助。
参考文章:https://www.cnblogs.com/linwene/p/10169545.htmlspa