移动端复杂表格表头

  • 2019 年 11 月 13 日
  • 笔记

复杂表格表头

前言

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

效果

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

table.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,                  },                    ]          }      },      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

最终效果就如上图。