微信小程序表格组件--固定表头、自适应列宽、单元格点击事件支持、斑马线样式

ScrollableFixedHeaderTable

一个具有固定表头自适应列宽单元格点击事件支持斑马线样式的微信小程序表格组件(原生开发)。

动机

浏览了不少微信小程序组件库,发现都没有表格组件,可能大家认为微信小程序上展示表格没有必要?之后又在github上找,发现不少组件只监听表格的行点击事件,而我需要监听某一具体单元格的点击事件,所以写下了此份组件

版本更新

2024/6/6:
1. 修复了“无法在一页面内同时展示该表格及其余组件的问题”

真机演示

在这里插入图片描述

功能特性

  • 固定表头:表头始终保持在屏幕顶部,方便用户在查看表格数据时始终保持对列标题的参考;
  • 点击事件支持:支持单元格点击事件,以便在点击每个单元格时(除表头外)执行自定义操作;
  • 可滚动表格内容:表格内容可以在水平和垂直方向上滚动,以显示更多的数据;
  • 自适应列宽:根据最长的表头元素长度计算最小列宽,使表头与表格数据保持同宽;
  • 斑马线样式:表格行间隔的背景颜色不同,提高数据的可读性;
  • 可自定义表头背景颜色和单元格无数据时的显示内容。

属性列表

属性类型默认值必填说明
column-namesArray[]yes表头的列名数组
table-dataArray[]yes表格数据的二维数组
bind:celltapeventhandle-yes点击每个单元格时(除表头外)执行自定义操作。其中,形参的e.detail.row得到当前单元格的行下标;e.detail.col得到当前单元格的列下标
stripeBooleantrueno是否显示斑马纹
borderlineBooleanfalseno是否显示边框
header-backgroundString‘#2d66cf’no表头的背景颜色
no-data-msgString‘无’no单元格无数据时的显示内容

表格组件源码

  1. ScrollableFixedHeaderTable.js
// components/ScrollableFixedHeaderTable/ScrollableFixedHeaderTable.js
Component({

  /**
   * 组件的属性列表
   */
  properties: {
    columnNames: {
      type: Array,
      value: []
    },
    tableData: {
      type: Array,
      value: []
    },
    //单元格无数据时的显示内容
    noDataMsg:{
      type:String,
      value: '无'
    },
    //是否显示斑马纹
    stripe:{
       type:Boolean,
       value:true
    },
    //是否显示列边框
    borderline:{
      type:Boolean,
      value:false
    },
    //表头背景颜色
    headerBackground:{
      type:String,
      value:'#2d66cf'
    }

  },

  /**
   * 组件的初始数据
   */
  data: {
    minWidth: 80,
    headerHeight: 3,
    headerScrollLeft: 0
  },

  /**
   * 组件的方法列表
   */
  methods: {
    calcMinWidth: function (cols) {
      //由最长的表头元素长度计算(表头与表格数据的)最小宽度
      var _max = -1;
      const padding = 5;
      const charWidth = 15;
      for (let i = 0; i < cols.length; i++) {
        if (cols[i].length > _max) {
          _max = cols[i].length;
        }
      }
      const maxTextLength = _max;
      return padding * 2 + charWidth * maxTextLength;
    },

    //实现表头的同步滑动
    syncScroll: function (e) {
      const scrollLeft = e.detail.scrollLeft;
      this.setData({
        headerScrollLeft: scrollLeft
      });
    },

    onCellTap: function (e) {
      this.triggerEvent('celltap', e.currentTarget.dataset);
    }
  },

  ready: function () {
    const minWidth = this.calcMinWidth(this.data.columnNames);
    this.setData({
      minWidth
    });
  }
});
  1. ScrollableFixedHeaderTable.json
{
  "component": true,
  "styleIsolation": "apply-shared",
  "usingComponents": {}
}
  1. ScrollableFixedHeaderTable.wxml
<!--components/ScrollableFixedHeaderTable/ScrollableFixedHeaderTable.wxml-->
<!-- 表头,此处禁用了表头的指针事件,即表头将不会响应触摸滚动事件。表头的滚动由表格内容的滑动引起。 -->
<scroll-view class="header" scroll-x="true" scroll-left="{{headerScrollLeft}}" style="pointer-events: none; position: sticky; top: 0; z-index: 100;">
  <view class="tr">
    <view class="th" style="min-width: {{minWidth}}px; {{borderline ? 'border: 0.1px solid black;' : ''}} background:{{headerBackground}}" wx:for="{{columnNames}}" wx:key="*this" wx:for-item="colName">
      <text>{{colName}}</text>
    </view>
  </view>
</scroll-view>

<!-- 表格内容 -->
<!-- table数组的每个数组元素作为rowDatas,rowDatas是一个包含该行所有信息的数组,故还可以循环展开 -->
<scroll-view class="content" wx:if="{{columnNames.length != 0}}" scroll-x="true" bindscroll="syncScroll" style="padding-top: {{headerHeight}}rem;">

  <view class="tr {{stripe ? 'tr-stripe' : ''}}" wx:for="{{tableData}}" wx:key="*this" wx:for-index='rowIndex' wx:for-item="rowData" >
    <view class="td" style=" min-width: {{minWidth}}px; {{borderline ? 'border: 0.1px solid black;' : ''}} {{(stripe && (rowIndex % 2 == 1)) ? 'background: #f0eeee;' : '' }}" wx:for="{{rowData}}" wx:key="*this" wx:for-item="detail" wx:for-index='colIndex' bindtap="onCellTap" data-row="{{rowIndex}}" data-col="{{colIndex}}">
      {{(detail.length == 0 )? noDataMsg : detail}}
    </view>
  </view>

</scroll-view>
  1. ScrollableFixedHeaderTable.wxss
/* components/ScrollableFixedHeaderTable/ScrollableFixedHeaderTable.wxss */
.tr {
  display: flex;
  align-items: center;
  height: 3rem;
  width: 100%;
}

.td, .th {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 0 10px;
  height: 100%;
}

.th {
  color: #fff;
  font-size: 15px;
}

.tr-stripe {
  background: #fff;
}
.tr-stripe:nth-child(2n) {
  background: #f0eeee;
}

.td {
  font-size: 12px;
}

使用示例

将以上4份源文件添加至当前目录下的同一文件夹ScrollableFixedHeaderTable,并对需要使用此组件的页面json文件添加以下代码以引入组件
index.json

{
  "usingComponents": {
    "scrollable-fixed-header-table": "./ScrollableFixedHeaderTable"
  }
}

在需要使用此组件的页面的WXML文件中,添加以下代码以使用组件:

index.wxml

<scrollable-fixed-header-table
  column-names="{{columnNames}}"
  table-data="{{table}}"
  bind:celltap="onCellTap"
  stripe="{{stripe}}"
  borderline="{{borderline}}"
  header-background="{{headerbg}}"
  no-data-msg=""
/>

index.js

Page({
  data: {
    stripe: true,
    borderline:false,
    headerbg:'#2d66cf',
    columnNames: ['Header 1', 'Header 2', 'Header 3', 'Header 4'],
    table: [
      ['', 'Row 1, Col 2', 'Row 1, Col 3', 'Row 1, Col 4'],
      ['Row 2, Col 1', 'Row 2, Col 2', 'Row 2, Col 3', 'Row 2, Col 4'],
      ['Row 3, Col 1', 'Row 3, Col 2', 'Row 3, Col 3', 'Row 3, Col 4'],
      ['Row 4, Col 1', 'Row 4, Col 2', 'Row 4, Col 3', 'Row 4, Col 4'],
      ['Row 5, Col 1', 'Row 5, Col 2', 'Row 5, Col 3', 'Row 5, Col 4'],
      ['Row 6, Col 1', 'Row 6, Col 2', 'Row 6, Col 3', 'Row 6, Col 4'],
      ['Row 7, Col 1', 'Row 7, Col 2', 'Row 7, Col 3', 'Row 7, Col 4'],
      ['Row 8, Col 1', 'Row 8, Col 2', 'Row 8, Col 3', 'Row 8, Col 4'],
      ['Row 9, Col 1', 'Row 9, Col 2', 'Row 9, Col 3', 'Row 9, Col 4'],
      ['Row 10, Col 1', 'Row 10, Col 2', 'Row 10, Col 3', 'Row 10, Col 4'],
      ['Row 11, Col 1', 'Row 11, Col 2', 'Row 11, Col 3', 'Row 11, Col 4'],
      ['Row 12, Col 1', 'Row 12, Col 2', 'Row 12, Col 3', 'Row 12, Col 4'],
      ['Row 13, Col 1', 'Row 13, Col 2', 'Row 13, Col 3', 'Row 13, Col 4'],
      ['Row 14, Col 1', 'Row 14, Col 2', 'Row 14, Col 3', 'Row 14, Col 4'],
      ['Row 15, Col 1', 'Row 15, Col 2', 'Row 15, Col 3', 'Row 15, Col 4'],
      ['Row 16, Col 1', 'Row 16, Col 2', 'Row 16, Col 3', 'Row 16, Col 4'],
      ['Row 17, Col 1', 'Row 17, Col 2', 'Row 17, Col 3', 'Row 17, Col 4'],
      ['Row 18, Col 1', 'Row 18, Col 2', 'Row 18, Col 3', 'Row 18, Col 4'],
      ['Row 19, Col 1', 'Row 19, Col 2', 'Row 19, Col 3', 'Row 19, Col 4'],
      ['Row 20, Col 1', 'Row 20, Col 2', 'Row 20, Col 3', 'Row 20, Col 4'],

    ]
  },
  
  onCellTap: function (e) {
    console.log('点击的单元格行索引为:', e.detail.row, ' 列索引为:', e.detail.col);
  }

});

注意事项

  • 本组件仅适用于微信小程序,不支持其他平台;
  • 暂不支持多级表头
  • 没有处理表头点击事件的函数。
  • 60
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
微信小程序提供的组件中,Grid(网格)是一种非常强大和灵活的布局组件,可以实现多种不同的网格视图。其中一种常见的应用场景是行和列同时滑动,从而使用户可以快速浏览并选择不同的内容。 要实现这种功能,首先需要在 Grid 组件中设置 scroll-x 和 scroll-y 两个属性为 true,以允许同时滑动水平和垂直方向。同时,还需要设置每个网格项(即每个单元格)的宽度和高度,以确保它们能够按照预期的方式排列在网格中。 具体的实现方法可以分为以下几个步骤: 1. 在 wxml 文件中添加 Grid 组件,并设置 scroll-x 和 scroll-y 属性为 true。 ```html <view class="grid-container"> <grid scroll-x scroll-y> <!-- 网格项内容 --> </grid> </view> ``` 2. 在样式表中设置网格容器的高度和宽度,以及网格项的宽度和高度。 ```css .grid-container { width: 100%; height: 500rpx; } .grid-item { width: 33.3%; height: 200rpx; } ``` 3. 在 js 文件中动态设置网格项的内容和数量。 ```js Page({ data: { gridData: [] }, onLoad: function () { // 从服务器获取网格项数据 // ... // 将数据存储到 data 中 this.setData({ gridData: [ { text: '网格项1' }, { text: '网格项2' }, { text: '网格项3' }, { text: '网格项4' }, { text: '网格项5' }, // ... ] }); } }) ``` 4. 在 wxml 文件中使用 wx:for 循环遍历网格数据,并将网格项的文本内容显示出来。 ```html <view class="grid-container"> <grid scroll-x scroll-y> <block wx:for="{{ gridData }}" wx:key="{{ index }}"> <grid-item class="grid-item">{{ item.text }}</grid-item> </block> </grid> </view> ``` 综上所述,通过上述步骤,即可实现微信小程序组件 Grid 的行和列同时滑动的功能。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_DDO

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值