vue移动端复杂表格表头,固定表头与固定第一列

简介: 最近做移动端的h5项目,要做一个可配置表头的复杂表格,网上找了很久也没什么好方法,结合网上的一些例子,在此做一了一个完整的vue版的例子。

前言


最近做移动端的h5项目,要做一个可配置表头的复杂表格,网上找了很久也没什么好方法,结合网上的一些例子,在此做一了一个完整的vue版的例子。


效果


无图无真相,先上最终效果图再说 。


微信图片_20220512140224.gif


方法一:iscroll 插件版


第一步:npm install


引入 iscroll


npm i iscroll --save


第二步:封装


对插件再做一层封装,封装成 iscrollTable.js 方便调用,代码如下:


// 统一使用
const iScollProbe = require('iscroll/build/iscroll-probe');
let scroller = null;
let Selector = "";
export function createIScroller(selector) {
  Selector = selector;
  scroller = new iScollProbe(Selector, {
    preventDefault: false,  // 阻止浏览器滑动默认行为
    probeType: 3, //需要使用 iscroll-probe.js 才能生效 probeType : 1 滚动不繁忙的时候触发 probeType : 2 滚动时每隔一定时间触发 probeType : 3   每滚动一像素触发一次
    mouseWheel: true, //是否监听鼠标滚轮事件。
    scrollX: true,  // 启动x轴滑动
    scrollY: true,  // 启动y轴滑动
    // momentum: false,
    lockDirection: false,
    snap: false, //自动分割容器,用于制作走马灯效果等。Options.snap:true// 根据容器尺寸自动分割
    //snapSpeed: 400,
    scrollbars: false, //是否显示默认滚动条
    freeScroll: true, //主要在上下左右滚动都生效时使用,可以向任意方向滚动。
    deceleration: 0.0001, //滚动动量减速越大越快,建议不大于 0.01,默认:0.0006
    disableMouse: true, //是否关闭鼠标事件探测。如知道运行在哪个平台,可以开启它来加速。
    disablePointer: true, //是否关闭指针事件探测。如知道运行在哪个平台,可以开启它来加速。
    disableTouch: false, //是否关闭触摸事件探测。如知道运行在哪个平台,可以开启它来加速。
    eventPassthrough: false, //使用 IScroll 的横轴滚动时,如想使用系统立轴滚动并在横轴上生效,请开启。
    bounce: false //是否启用弹力动画效果,关掉可以加速
  });
  scroller.on('scroll', updatePosition);
  scroller.on('scrollEnd', updatePosition);
  scroller.on('beforeScrollStart', function () {
    scroller.refresh();
  });
  function updatePosition() {
    let frozenCols = document.querySelectorAll(selector + ' table tr td.cols');
    let frozenRows = document.querySelectorAll(selector + ' table tr th.rows');
    let frozenCrosses = document.querySelectorAll(selector + ' table tr th.cross');
    for (let i = 0; i < frozenCols.length; i++) {
      frozenCols[i].style.transform = 'translate(' + -1 * this.x + 'px, 0px) translateZ(0px)';
    }
    for (let i = 0; i < frozenRows.length; i++) {
      frozenRows[i].style.transform = 'translate(0px, ' + -1 * this.y + 'px) translateZ(0px)';
    }
    for (let i = 0; i < frozenCrosses.length; i++) {
      frozenCrosses[i].style.transform = 'translate(' + -1 * this.x + 'px,' + -1 * this.y + 'px) translateZ(0px)';
    }
  }
  return scroller;
}
export function refreshScroller() {
  if (scroller === null) {
    console.error("先初始化scroller");
    return;
  }
  setTimeout(() => {
    scroller.refresh();
    scroller.scrollTo(0, 0);
    let frozenCols = document.querySelectorAll(Selector + ' table tr td.cols');
    let frozenRows = document.querySelectorAll(Selector + ' table tr th.rows');
    let frozenCrosses = document.querySelectorAll(Selector + ' table tr th.cross');
    for (let i = 0; i < frozenCols.length; i++) {
      frozenCols[i].style.transform = 'translate(0px, 0px) translateZ(0px)';
    }
    for (let i = 0; i < frozenRows.length; i++) {
      frozenRows[i].style.transform = 'translate(0px, 0px) translateZ(0px)';
    }
    for (let i = 0; i < frozenCrosses.length; i++) {
      frozenCrosses[i].style.transform = 'translate(0px, 0px) translateZ(0px)';
    }
  }, 0);
}


第三步:使用


引用前面的自己封装的iscrollTable.js,用到的table.vue的具体代码如下:


<template>
    <div class="pages-tables " id="pages-tables">
        <div class="waterMask" id="watermark"></div>
        <div class="rolling-table meal-table" ref="tableBox" :style="{height: maxHeight + 'px'}">
            <table class="table" id="table" cellpadding="0" cellspacing="0" ref="rollingTable">
                <tr v-for="(x,i) in xList" :key="i">
                    <th class="rows " :class="{'cross': index == 0 && i == 0}" v-for="(l,index) in x" :key="index" :colspan="l.colspan" :rowspan="l.rowspan">{{l.name}}</th>
                </tr>
                <tr v-for="(l,i) in yList" :key="i + 'a'">
                    <template v-for="(x, xKey) in xField">
                        <td v-for="(ll,yKey) in l" :key="yKey" v-if="x === yKey" :class="{'cols': yKey == xField[0]}">
                            {{ yList[i][yKey]}}
                        </td>
                    </template>
                </tr>
                <tr></tr>
            </table>
        </div>
    </div>
</template>
<script>
import { createIScroller, refreshScroller } from "libs/iscrollTable";
import { addWaterMarker } from "libs/common/common";
export default {
    data() {
        return {
            maxHeight:'100%',
            scroll: {
                scroller: null
            },
            xList: [
                [
                    {
                        field_name: "statis_date",
                        name: "第一行合并3行1列",
                        colspan: 1, //指定单元格 横向 跨越的 列数
                        rowspan: 3, //指定单元格 纵向 跨越的 行数
                    },
                    {
                        field_name: "custom_field",
                        name: "第一行合并2列",
                        colspan: 2,
                        rowspan: 1,
                    },
                    {
                        field_name: "custom_field",
                        name: "第一行合并2列",
                        colspan: 2,
                        rowspan: 1,
                    },
                    {
                        field_name: "custom_field",
                        name: "第一行合并3列",
                        colspan: 3,
                        rowspan: 1,
                    },
                ],
                [
                    {
                        field_name: "custom_field",
                        name: "第二行日期",
                        colspan: 1, //指定单元格 横向 跨越的 列数
                        rowspan: 1, //指定单元格 纵向 跨越的 行数
                    },
                    {
                        field_name: "custom_field",
                        name: "第二行日期合并2列",
                        colspan: 2,
                        rowspan: 1,
                    },
                    {
                        field_name: "custom_field",
                        name: "第二行日期合并2列",
                        colspan: 2,
                        rowspan: 1,
                    },
                    {
                        field_name: "custom_field",
                        name: "第二行日期合并3列",
                        colspan: 3,
                        rowspan: 1,
                    },
                ],
                [
                    {
                        field_name: "area_name",
                        name: "第三行当月新增",
                        colspan: 1,  //指定单元格 横向 跨越的 列数
                        rowspan: 1, //指定单元格 纵向 跨越的 行数
                    },
                    {
                        field_name: "area_name1",
                        name: "第三行当月新增1",
                        colspan: 1,
                        rowspan: 1,
                    },
                    {
                        field_name: "area_name2",
                        name: "第三行当月新增2",
                        colspan: 1,
                        rowspan: 1,
                    },
                    {
                        field_name: "area_name3",
                        name: "第三行当月新增3",
                        colspan: 1,
                        rowspan: 1,
                    },
                    {
                        field_name: "area_name4",
                        name: "第三行当月新增4",
                        colspan: 1,
                        rowspan: 1,
                    },
                    {
                        field_name: "area_name5",
                        name: "第三行当月新增5",
                        colspan: 1,
                        rowspan: 1,
                    },
                    {
                        field_name: "area_name6",
                        name: "第三行当月新增6",
                        colspan: 1,
                        rowspan: 1,
                    },
                ],
            ],
            xField: ['statis_date', 'area_name', "area_name1", "area_name2", "area_name3", "area_name4", "area_name5", "area_name6",],
            yList: [
                {
                    area_name: "新增数据开始",
                    area_name1: "新增数据开始1",
                    area_name2: "新增数据开始2",
                    area_name3: "新增数据开始3",
                    area_name4: "新增数据开始4",
                    area_name5: "新增数据开始5",
                    area_name6: "新增数据开始6",
                    statis_date: 100007,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据最后",
                    area_name1: "新增数据最后1",
                    area_name2: "新增数据最后2",
                    area_name3: "新增数据最后3",
                    area_name4: "新增数据最后4",
                    area_name5: "新增数据最后5",
                    area_name6: "新增数据最后6",
                    statis_date: 222222,
                }
            ]
        }
    },
    mounted() {
        this.maxHeight = window.screen.height
        this.scroll.scroller = createIScroller(".meal-table");
        // addWaterMarker(document.getElementById('watermark'))
    }
}
</script>
<style lang="less" scoped>
.pages-tables {
  -webkit-overflow-scrolling: touch; // ios滑动顺畅
  position: relative;
}
.rolling-table {
    height: 100%;
    font-size: 0.28rem;
    color: #86939a;
    background-color: #fff;
    width: 100%;
    -webkit-overflow-scrolling: touch;
    position: relative;
    top: 0;
    overflow: hidden;
  }
.rows {
    position: relative;
    z-index: 3;
}
.cross {
    position: relative;
    z-index: 5;
}
table td {
  border: 0px solid #000;
  font-size: 0.32rem;
  background: #fff;
}
::-webkit-scrollbar {
    display: none;
}
.table {
//   border-collapse: collapse; //去掉重复的border
  color: #86939e;
  font-size: 0.32rem;
  border: 0px solid #000;
  min-height: 100%;
  text-align: center;
  td {
    border-bottom: 0.02rem solid #eee;
    white-space: nowrap;
    height: 0.86rem;
    line-height: 0.86rem;
    padding: 0 0.2rem;
  }
  th {
    color: #43484d;
    white-space: nowrap;
    height: 0.74rem;
    line-height: 0.74rem;
    padding: 0rem 0.3rem;
    background-color: #f3f4f6;
    font-weight: normal;
    padding-bottom: 0;
    padding-top: 0;
    border: 0.02rem solid red;
  }
}
tr{
    position: relative;
    background-color: #fff;
    &:nth-of-type(odd){
        td{
            // background-color: pink;
        }
    }
}
</style>


注意点:


  1. table 外的盒子 .rolling-table 要设置高度,不然向上滚动失效


2.固定和行与列,即:rows、cross 的position要设为relative


最终效果就如上图。


方法二: 结合css,自定义封装版


原理


因为除了表头和第一列,其他都可以滚动所以需要:

1.一个展示的table表格

2.一个用来覆盖上表头的 thead,一个用来覆盖左上角的 div,一个固定在第一列的 tbody。


  1. 展示的table表格放在最底层,覆盖上表头的 thead固定定位在最上面,固定在第一列的 tbody固定定位在最左边,左上角的 div固定是左上角且z-index最大,在最上层。
  2. 固定的表格头部与第一列的宽、高、行高都是通过获取真实的表格的宽高来设定的。
  3. 通过展示的table表格的上下滚动从而带动固定在第一列的 tbody向上滚动,向左右滚动带动覆盖上表头的 thead的左右滚动。

完整代码如下:


<template>
    <div class="pages" id="pages" :style="{height: maxHeight + 'px'}">
        <table id="table" class="table" cellpadding="0" cellspacing="0">
            <thead v-show="showFixedHeaderCloFirst" class="fixedThead" id="fixedThead" :style="{left: fixedTheadLeft}">
                <tr v-for="(x,i) in xList"   :key="i+'a'">
                    <th v-for="(l,i) in x" :key="i" :colspan="l.colspan" :rowspan="l.rowspan">{{l.name}}</th>
                </tr>
            </thead>
            <div v-show="showFixedHeaderCloFirst" class="fixedHeaderCenter" id="fixedHeaderCenter" :style="{'line-height': firstCloHeight + 'px',width: firstCloWidth-1 + 'px'}">{{xList[0][0].name}}</div>
            <tbody v-show="showFixedHeaderCloFirst" class="fixedHeaderCloFirst" id="fixedHeaderCloFirst" :style="{'top': fixedHeaderCloFirstTop ,'height': fixedHeaderCloFirstHeight}">
                <tr v-for="(l,i) in yList" :key="i" :style="{width: firstCloWidth + 'px',height: cloFirstLineHeight + 'px'}">
                    <td :style="{width: firstCloWidth + 'px',height: cloFirstLineHeight -1 + 'px' }">{{l.statis_date }} </td>
                </tr>
            </tbody>
            <thead >
                <tr v-for="(x,index) in xList"   :key="index+'b'">
                    <th :class="{firstCol: index == 0 && i == 0}" v-for="(l,i) in x" :key="i" :colspan="l.colspan" :rowspan="l.rowspan">{{l.name}}</th>
                </tr>
            </thead>
            <tbody id="tbody">
                <tr  v-for="(l,i) in yList" :key="i">
                    <td v-for="(x,xKey) in xField" :key="xKey">
                        <div v-for="(ll,yKey) in l" v-if="x === yKey" :key="yKey" :class="{'tables-content-item-yellow':yList[i][yKey] > 0 && validateVal(x),'tables-content-item-green':yList[i][yKey] <= 0 && validateVal(x),}">
                            {{ yList[i][yKey]}}
                        </div>
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
</template>
<script>
export default {
    data() {
        return {
            maxHeight: '100%',
            fixedTheadLeft: 0,
            fixedHeaderCloFirstTop: 0,
            fixedHeaderCloFirstHeight: '100%',
            th: [],
            tl: [],
            temp: [],
            firstCloWidth: 0,
            firstCloHeight: 0,
            showFixedHeaderCloFirst: false,
            cloFirstLineHeight: '0',
            fixedCol: false,
            fixedHeader: false,
            fixedA1: false,
            hLeft: 0,
            hHeight: 0,
            xList: [
                [
                    {
                        field_name: "statis_date",
                        name: "第一行合并3行1列",
                        colspan: 1, //指定单元格 横向 跨越的 列数
                        rowspan: 3, //指定单元格 纵向 跨越的 行数
                    },
                    {
                        field_name: "custom_field",
                        name: "第一行合并2列",
                        colspan: 2,
                        rowspan: 1,
                    },
                    {
                        field_name: "custom_field",
                        name: "第一行合并2列",
                        colspan: 2,
                        rowspan: 1,
                    },
                    {
                        field_name: "custom_field",
                        name: "第一行合并3列",
                        colspan: 3,
                        rowspan: 1,
                    },
                ],
                [
                    {
                        field_name: "custom_field",
                        name: "第二行日期",
                        colspan: 1, //指定单元格 横向 跨越的 列数
                        rowspan: 1, //指定单元格 纵向 跨越的 行数
                    },
                    {
                        field_name: "custom_field",
                        name: "第二行日期合并2列",
                        colspan: 2,
                        rowspan: 1,
                    },
                    {
                        field_name: "custom_field",
                        name: "第二行日期合并2列",
                        colspan: 2,
                        rowspan: 1,
                    },
                    {
                        field_name: "custom_field",
                        name: "第二行日期合并3列",
                        colspan: 3,
                        rowspan: 1,
                    },
                ],
                [
                    {
                        field_name: "area_name",
                        name: "第三行当月新增",
                        colspan: 1,  //指定单元格 横向 跨越的 列数
                        rowspan: 1, //指定单元格 纵向 跨越的 行数
                    },
                    {
                        field_name: "area_name1",
                        name: "第三行当月新增1",
                        colspan: 1,
                        rowspan: 1,
                    },
                    {
                        field_name: "area_name2",
                        name: "第三行当月新增2",
                        colspan: 1,
                        rowspan: 1,
                    },
                    {
                        field_name: "area_name3",
                        name: "第三行当月新增3",
                        colspan: 1,
                        rowspan: 1,
                    },
                    {
                        field_name: "area_name4",
                        name: "第三行当月新增4",
                        colspan: 1,
                        rowspan: 1,
                    },
                    {
                        field_name: "area_name5",
                        name: "第三行当月新增5",
                        colspan: 1,
                        rowspan: 1,
                    },
                    {
                        field_name: "area_name6",
                        name: "第三行当月新增6",
                        colspan: 1,
                        rowspan: 1,
                    },
                ],
            ],
            xField: ['statis_date', 'area_name', "area_name1", "area_name2", "area_name3", "area_name4", "area_name5", "area_name6",],
            yList: [
                {
                    area_name: "新增数据开始",
                    area_name1: "新增数据开始1",
                    area_name2: "新增数据开始2",
                    area_name3: "新增数据开始3",
                    area_name4: "新增数据开始4",
                    area_name5: "新增数据开始5",
                    area_name6: "新增数据开始6",
                    statis_date: 100007,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据",
                    area_name1: "新增数据1",
                    area_name2: "新增数据2",
                    area_name3: "新增数据3",
                    area_name4: "新增数据4",
                    area_name5: "新增数据5",
                    area_name6: "新增数据6",
                    statis_date: 201807,
                },
                {
                    area_name: "新增数据最后",
                    area_name1: "新增数据最后1",
                    area_name2: "新增数据最后2",
                    area_name3: "新增数据最后3",
                    area_name4: "新增数据最后4",
                    area_name5: "新增数据最后5",
                    area_name6: "新增数据最后6",
                    statis_date: 222222,
                }
            ]
        }
    },
    filters: {
        dateFromt: function (value) {
            if (!value) return ''
            value = value.toString()
            return value.slice(4)
        },
    },
    methods: {
        // 返回
        vdVal(val, value) {
            return value
        },
        // 是否包含 % 标志,有就要颜色控制
        validateVal(value) {
            let flag = false
            this.xList.forEach((e, i) => {
                if (e.zd_name == value) {
                    if (e.zx_name.includes('%')) {
                        flag = true
                    }
                }
            })
            return flag
        },
        $$(dom){
            return document.getElementById(dom)
        },
        savePosition(){
            this.maxHeight = window.screen.height
            this.$$("pages").onscroll = (()=> {
                let offsetHeight = this.$$("fixedHeaderCenter").offsetHeight
                let scrollTop = offsetHeight + 1 - this.$$("pages").scrollTop
                this.fixedTheadLeft =  - this.$$("pages").scrollLeft + 'px'
                this.fixedHeaderCloFirstTop = scrollTop + 'px'
                console.log("scrollTop:",scrollTop)
                console.log("this.fixedHeaderCloFirstTop:",this.fixedHeaderCloFirstTop)
            });
            // this.$$("fixedHeaderCloFirst").onscroll = (()=> {
            //     let offsetHeight = this.$$("fixedHeaderCenter").offsetHeight
            //     let scrollTop = - this.$$("fixedHeaderCloFirst").scrollTop
            //     this.$$("pages").style.left =  - this.$$("fixedHeaderCloFirst").scrollLeft + 'px'
            //     this.$$("table").style.top =  scrollTop + 'px'
            // });
        }
    },
    mounted() {
        setTimeout(()=>{
            this.firstCloWidth = document.getElementsByClassName("firstCol")[0].offsetWidth 
            this.firstCloHeight = document.getElementsByClassName("firstCol")[0].offsetHeight-1
            this.fixedHeaderCloFirstHeight = this.$$("tbody").offsetHeight + 'px'
            this.cloFirstLineHeight = this.$$("tbody").children[0].offsetHeight  + 'px'
            this.fixedHeaderCloFirstTop = this.firstCloHeight + 3 + 'px'
            this.showFixedHeaderCloFirst = true
            this.savePosition()
        },1000)
    },
}
</script>
<style lang="less" scoped>
::-webkit-scrollbar {
    display: none;
}
.pages{
    overflow: scroll;
    height: 100%;
}
.fixedHeaderCenter{
    border: 1px solid red;
    background-color: #f3f4f6;
    color: #43484d;
    text-align: center;
    // padding: 0 0.3rem;
    position: fixed;
    left: 0;
    top: 0;
    z-index: 9999;
}
.fixedHeaderCloFirst{
    // border-bottom: 1px solid #eee;
    height: 100%;
    line-height: 0.86rem;
    background: #fff;
    white-space: nowrap;
    text-align: center;
    position: fixed;
    left: 0;
    top: 0;
    th,td{
        padding: 0;
    }
    // overflow: scroll;
    div{
        background-color: #fff;
        border-bottom: 1px solid #eee;
    }
}
@main-color-green: #269513;
@main-color-yellow: #fc9d2e;
table {
  position: relative;
  color: #86939e;
  font-size: 0.32rem;
  border: 0px solid #000;
  min-height: 100%;
  text-align: center;
  white-space:nowrap;
  td {
    border-bottom: 1px solid #eee;
    white-space: nowrap;
    height: 0.86rem;
    line-height: 0.86rem;
    padding: 0 0.2rem;
    white-space:nowrap;
  }
  th {
      white-space:nowrap;
    color: #43484d;
    white-space: nowrap;
    height: 0.74rem;
    line-height: 0.74rem;
    padding: 0rem 0.3rem;
    background-color: #f3f4f6;
    font-weight: normal;
    padding-bottom: 0;
    padding-top: 0;
    border: 1px solid red;
  }
}
.tables-content-item-green {
  color: @main-color-green;
}
.tables-content-item-yellow {
  color: @main-color-yellow;
}
table {
    font-size: 0.3rem;
    // margin: 300px;
    border-collapse:collapse
}
.fixedThead{
    background: lightblue;
    position: fixed;
    top: 0 ;
    z-index: 2;
}
/*固定表头的样式*/
.fixedHeader {
    background: lightblue;
    position: fixed;
    top: 0 ;
    z-index: 2;
}
</style>


最终效果图如下:


微信图片_20220512140425.gif


不过这个版本的上下滚动时的精准计算有点误差。


推荐第一种方式。
相关文章
|
3天前
|
资源调度 JavaScript 前端开发
【vue】vue中的路由vue-router,vue-cli脚手架详细使用教程
【vue】vue中的路由vue-router,vue-cli脚手架详细使用教程
|
3天前
|
JavaScript
【vue】深入探讨vue中组件间多种传值方式
【vue】深入探讨vue中组件间多种传值方式
【vue】深入探讨vue中组件间多种传值方式
|
3天前
|
JavaScript 前端开发
vue组件化开发流程梳理,拿来即用
vue组件化开发流程梳理,拿来即用
|
4天前
|
移动开发 JavaScript 前端开发
Vue Router的介绍与引入
Vue Router的介绍与引入
|
8天前
|
JavaScript
【vue】如何跳转路由到指定页面位置
【vue】如何跳转路由到指定页面位置
12 0
|
8天前
|
资源调度 JavaScript 前端开发
【vue】vue-cli版本选择和比较(vue-cli3.0新版本如何创建项目)
【vue】vue-cli版本选择和比较(vue-cli3.0新版本如何创建项目)
16 1
|
8天前
|
JavaScript 前端开发
【vue】iview如何把input输入框和点击输入框之后的边框去掉
【vue】iview如何把input输入框和点击输入框之后的边框去掉
14 0
|
8天前
|
JavaScript UED
【vue】iview组件 DatePicker 日期选择器如何显示默认当前日期
【vue】iview组件 DatePicker 日期选择器如何显示默认当前日期
12 1
|
4天前
|
JavaScript 应用服务中间件 nginx
vue中404解决方法
vue中404解决方法
|
4天前
|
JavaScript
Vue 中如何模块化使用 Vuex
Vue 中如何模块化使用 Vuex