antd Tree树形结构可编辑,动态修改cell背景色的复杂表格心得

颛孙庆
2023-12-01

    最近由于业务要写了个比较复杂的表格,该表格的功能就是,有三层嵌套结构,可以动态改变指定值的背景色

写这个的时候真的是一头雾水,不知道该从哪下手,说下写这个的时候的难点在于,一定要和后端商量好数据结构是怎样的,例如虽然我们这是三层嵌套,但我只需要后端嵌套到第二层就好了,剩下的最后一层自己嵌一套就好了,另外因为与客户交互的过程这个在定义数据表格的时候一定要和后端说好,每条数据都要有自己的id,子id和父id要关联起来,另外在子项当中需要包含其父层的id,为的是在编辑的时候方便往上找到编辑数据的最顶层,其他就没有什么了,其他的多余操作都可以在Table中 clumon中的render中实现。好了不多哔哔,代码如下:

 <Table
                columns={columns}
                components={components}
                className="table-color"
                scroll={{ x: 1200, y: 360 }}
                dataSource={this.state.dataSource}
                bordered
                rowClassName={record => {
                  let className = ""
                  if (this.state.titleKey.includes(record.eSeries)) { return className = 'table-color-dust' }
                  // return className;
                }}
                expandedRowClassName={record => {
                  if (record.children && !record.isExpanable) {
                    return "table-color-close";
                  }
                }}
                rowKey={record => (record.parentKey || `${record.dataKey}`)}
                bordered={false}
                pagination={false}
                expandable={{
                  defaultExpandAllRows: true,
                  defaultExpandedRowKeys: ["1"],
                  expandIcon: ({ expanded, onExpand, record }) => {
                    if (record.children && !record.isExpanable) {
                      if (expanded) {
                        return <CaretDownOutlined style={{ fontSize: "14px" }} onClick={e => onExpand(record, e)} />;
                      } else {
                        return <CaretRightOutlined style={{ fontSize: "14px" }} onClick={e => onExpand(record, e)} />;
                      }
                    } else if (record.isExpanable) {
                      if (expanded) {
                        return isCentral() == 1 ? <span className={'cell-expandable'} onClick={e => onExpand(record, e)}><MinusOutlined style={{ marginBottom: 3, position: 'relative', left: "3px", fontSize: '10px' }} /></span> : ""
                      } else {
                        return isCentral() == 1 ? <span className={'cell-expandable'} onClick={e => onExpand(record, e)}><PlusOutlined style={{ marginBottom: 3, position: 'relative', left: "3px", fontSize: '10px' }} /></span> : ""
                      }
                    } else {
                      return '';
                    }
                  }

                }}
              // ref={ref => this.tableRef = ref}
              />

其中最关键的地方在于Table中的component这个属性,这其中封装了你的表头和可编辑单元格

const Cellcolumns = [{
      title: <div className="columns-header-T">Timeline</div>,
      dataIndex: 'eSeries',
      align: 'left',
      width: 80,
      className: "frist-list-setindex",
      editable: false,
      fixed: 'left',
      render: (text, record) => {
        const obj = {
          children: <div className='time-line-frist'>{text}</div>,
          props: {},
        };
        if (!this.state.titleKey.includes(record.eSeries)) {
          return <div className={`${text ? 'time-line-top' : ''} time-line`}>{text}</div>;
        } else {
          obj.props.colSpan = 2;
          return obj;
        }
      },
    },
.,
.,
.]; 
   const components = {
      body: {
        row: EditableRow,
        cell: EditTableCell,
      },
    };
    const columns = Cellcolumns.map((col) => {
      if (!col.editable) {
        return col;
      }


handleSave = async (row) => {
    row.children = undefined;
    row.isExpanable = undefined;
    if (this.state.changeData.findIndex(item => item.dataKey == row.dataKey) > -1) {
      //这里就是当有重复数据时(也就是说在编辑一条数据的时候在这里进行一个去重处理)
      let index = this.state.changeData.findIndex(item => item.dataKey == row.dataKey)
      this.state.changeData[index] = row;
    } else {
      this.state.changeData.push(row)
    }

    let copyOldDataSource = JSON.parse(JSON.stringify(this.state.oldDataSource));
    //吧没有修改过的数据拿过来进行一个深层赋值
    this.state.changeData.forEach(val => {
      //根据父id在数据中找出具体修改那一条数据
      let fadata = copyOldDataSource.find(item => item.parentKey == val.childrenKey)
      //找出这条数据之后再找出他在数组中对应的下标值
      let faIndex = copyOldDataSource.findIndex(item => item.parentKey == fadata.parentKey)
      //通过查找出来的数据找出修改的数据对应的是父数据children中的哪一个
      let childData = fadata.children.find(item => item.dataKey == val.dataKey)
      //找出数据拿到下标eSeries
      val.eSeries = childData.eSeries
      let childIndex = fadata.children.findIndex(item => item.dataKey == childData.dataKey)
      //拿到具体的坐标值之后进行更改
      copyOldDataSource[faIndex].children[childIndex] = val
    })

    //数据修改完之后在进行一个嵌套处理
    copyOldDataSource.forEach(e => {
      let indexStr = '';
      let count = 0;
      let targetEl;
      for (let i = 0; i < e.children.length; i++) {
        const el = e.children[i];
        if (i > 0) {
          if (!indexStr) {
            indexStr = e.children[i - 1].eSeries
          }
          if (el.eSeries === indexStr) {
            el.eSeries = '';
            count++;
            if (count === 2) {
              el.isExpanable = true;
              el.children = [];
              targetEl = el;
            }
            if (count > 2 && !!targetEl && !!targetEl.children) {
              targetEl.children.push(Object.assign({}, el));
              e.children.splice(i, 1);
              i--;
            }
          } else {
            indexStr = el.eSeries;
            count = 0;
            targetEl = void 0;
          }
        }
      }
    });
    this.setState({
      dataSource: copyOldDataSource,
    });

    // console.log(this.state.changeData, "修改值")
  };

好了,关键代码就是上面的,希望有帮助

 类似资料: