Taro模拟table表格搭配react实现方式

Taro模拟table表格搭配react实现方式

手机端使用表格场景较少。本文基础框架介绍:

  • taro:2.1.3
  • react:16.9.31(本文使用类组件)
  • css:stylus(和less、scss类似写法不一样)

父组件调用:仅供参考,详见子组件

// 组件
import Taro, {
    
     Component } from '@tarojs/taro'
import {
    
     Image, View } from '@tarojs/components'
import CustomTable from "@/components/CustomTable/CustomTable";
// styl
import './repairEndReport.styl'

class RepairEndReport extends Component {
    
    
  constructor(props) {
    
    
    super(props);
  }

  // eslint-disable-next-line react/sort-comp
  static options = {
    
    
    addGlobalClass: true
  };

  config = {
    
    
    navigationBarTitleText: '维修完结报告',
  }

  state = {
    
    
    detail: {
    
    },
    // 示例一 图片 视频
    columnsFault: [
      {
    
    
        title: '收货图片',
        dataIndex: 'arrivalExplainImages',
        width: '510',
      },
      {
    
    
        title: '修复前图片',
        dataIndex: 'machineRepairUrl',
        width: '510',
      }
    ],
    dataSourceFault: [{
    
    
      "arrivalExplainImages": ["https://img2.baidu.com/it/u=3094149767,177600321&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500", "https://img2.baidu.com/it/u=1035356506,3713698341&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500", "https://vd3.bdstatic.com/mda-kifgkdfisjk3skwi/hd/cae_h264_nowatermark/mda-kifgkdfisjk3skwi.mp4"],
      "machineRepairUrl": ["https://img0.baidu.com/it/u=236085137,1979895699&fm=253&fmt=auto&app=138&f=JPEG?w=360&h=360","https://img2.baidu.com/it/u=1527638636,152745451&fm=253&fmt=auto&app=138&f=JPEG?w=501&h=500"]
    }],

    // 示例二 文字
    columnsRepair: [
      {
    
    
        title: '序号',
        dataIndex: 'index',
        width: '100'
      },
      {
    
    
        title: '异常现象',
        dataIndex: 'anomalyList',
        width: '350'
      },
      {
    
    
        title: '故障点',
        dataIndex: 'textList',
        width: '350'
      },
      {
    
    
        title: '维修内容',
        dataIndex: 'repairContentList',
        width: '350'
      },
    ],
    dataSourceRepair: [
      {
    
    "index":1,"anomalyList":["开机无反应/间接反应","跳闸","其他(这是大其他)"],"textList":["定转子烧毁","开关无法通电/接触不良","控制板坏了","其他(1112)","内部漏电","其他(333)","其他(6666)"],"repairContentList":["更换定转子","更换控制板","其他(222)","更换漏电配件","其他(444)","其他(77777)"]},
      {
    
    "index":2,"anomalyList":["开机无反应/间接反应","跳闸","其他(这是大其他)"],"textList":["定转子烧毁","开关无法通电/接触不良","控制板坏了","其他(1112)","内部漏电","其他(333)","其他(6666)"],"repairContentList":["更换定转子","更换控制板","其他(222)","更换漏电配件","其他(444)","其他(77777)"]}
    ],
  }

  render() {
    
    
    const {
    
     columnsFault, columnsRepair, dataSourceFault, dataSourceRepair } = this.state;

    return (
      <View className='repairEndReport fs-28'>
        <View className='boxview m-t-18'>
          <View className='c-333'>示例一:图片视频</View>
          <CustomTable
            columns={
    
    columnsFault}
            dataSource={
    
    dataSourceFault}
          />
        </View>

        <View className='boxview m-t-18'>
          <View className='c-333'>示例二:文案列表</View>
          <CustomTable
            columns={
    
    columnsRepair}
            dataSource={
    
    dataSourceRepair}
          />
        </View>
      </View>
    )
  }
}

export default RepairEndReport

子组件表格 - jsx 部分

/* eslint-disable */
import {
    
     Text, Video, View } from '@tarojs/components';
import {
    
     Component } from '@tarojs/taro';
// styl
import './CustomTable.styl';

export default class CustomTable extends Component {
    
    
  constructor(props) {
    
    
    super(props);
  }

  // 是否加载全局css
  static options = {
    
    
    addGlobalClass: true
  };

  // 判断 数组类型
  checkItemType(item) {
    
    
    if (/\.(mp4|mov|ogm|wmv|asx|mpg|webm|ogv|mpeg|m4v|avi)$/.test(item)) {
    
    
      return 'video'
    } else if (/\.(png|jpg|gif|svg|webp|jpeg|bmp|tiff)$/.test(item)) {
    
    
      return 'img'
    } else {
    
    
      return 'text'
    }
  }

  // 点击图片看大图
  onTapImage(current, urls) {
    
    
    Taro.previewImage({
    
    
      urls,
      current
    });
  }

  render() {
    
    
    const {
    
     columns = [], dataSource = [] } = this.props

    // 重新计算 列表数据 匹配表头
    const newDataSource = dataSource.map(itemTr => {
    
    
      return columns.map(itemTd => {
    
    
        const newData = Array.isArray(itemTr[itemTd.dataIndex]) ? itemTr[itemTd.dataIndex] : [itemTr[itemTd.dataIndex] || ''];
        return {
    
    
          ...itemTd,
          data: newData,
          type: this.checkItemType(newData[0]),
        }
      })
    })

    // 计算每列的宽度
    let tableWidth = 0;
    columns.map(i => tableWidth += parseFloat(i.width))

    return (
      <View className='custom-table m-t-20'>
        <View style={
    
    {
    
    'width': tableWidth ? tableWidth + 'rpx' : '100%'}}>
          {
    
    /* 渲染表头 */}
          <View className='custom-table-header flex-row-between-center fs-26 c-666 bold'>
            {
    
    columns.map((item, index) => (
              <View className='flex-row-start-center tableDataItem' style={
    
    {
    
    'width': item.width ? item.width + 'rpx' : 'auto'}} key={
    
    `tableData-columns${
      
      index}`}>{
    
    item.title}</View>
            ))}
          </View>

          {
    
    /* 表格 body */}
          {
    
    newDataSource.length > 0 ? newDataSource.map((itemTr, indexTr) => (
            // 模拟tr
            <View key={
    
    `dataSource${
      
      indexTr}`} className='custom-table-body flex-row-between-start fs-28 c-333'>
              {
    
    /* 模拟 td */}
              {
    
    itemTr.map((itemTd, idxTd) => (
                <View className={
    
    `tableDataItem fs-28`} key={
    
    `tableData-itemTd${
      
      indexTr}-${
      
      idxTd}`} style={
    
    {
    
    'width': itemTd.width ? itemTd.width + 'rpx' : 'auto'}}>
                  {
    
    /* 模拟每个td里面多个图片或者视频 */}
                  {
    
    itemTd.data.map((item, idx) => (
                    this.checkItemType(item) === 'img' ? (
                      <Image
                        key={
    
    `tableData-itemTd-item-${
      
      indexTr}-${
      
      idxTd}-${
      
      idx}`}
                        className='image-video'
                        src={
    
    item}
                        onTap={
    
    () => this.onTapImage(item, itemTd.data)}
                      />
                    ) : this.checkItemType(item) === 'video' ? (
                      <Video
                        key={
    
    `tableData-itemTd-item-${
      
      indexTr}-${
      
      idxTd}-${
      
      idx}`}
                        className='image-video'
                        src={
    
    item}
                      />
                    ) : (
                      <View>{
    
    item}</View>
                    )
                  ))}
                </View>
              ))}
            </View>
          )) : (
            <View className='custom-table-body flex-row-center-center fs-28'>暂无数据</View>
          )}
        </View>
      </View>
    )
  }
}

子组件表格 - 样式 部分

.custom-table
  background: #fff
  overflow-x: auto;
  
  .flex-row-start-center
  	display flex
  	justify-content flex-start
  	align-items center
  	flex-direction row
  
  .custom-table-header
    height: 78px;
    line-height: 78px;
    background: #F6F6F6;
    border-radius: 8px 0px 0px 8px;

  .custom-table-body
    line-height: 78px;
    background: #fff;

  .tableDataItem
    min-width: 50px
    padding: 0 16px
  .image-video
    width: 154px
    height: 154px
    border-radius: 9px
    margin 15px 15px 15px 0


效果:

在这里插入图片描述

在这里插入图片描述

备注提示:

  • 表头数组匹配数组中dataIndex对应的每个td的key
  • 列表数据在使用时候重构了下内容。解决直接tbody内容使用columns时,渲染报错问题。原因未详查,无未遇到可不重构
  • 为了表格上下统一宽度,建议配置每个columns中的td宽度
  • 当有视频图片时,可以自动根据子元素视频图片个数计算宽度,有兴趣可以研究下

猜你喜欢

转载自blog.csdn.net/weixin_44461275/article/details/127738836