自定义列功能

需求

表格的列太多,需要实现一个自定义列的功能。
这个自定义列可能被用到多个地方,所以想要做成通用的

思考与实现

那么首先考虑的就是 hooks, hooks 可以对 columns 进行管理,最后输出一个筛选(自定义)过后的列,组件根据这个列进行渲染。

但是这就有一个问题,对于筛选的这个UI可能也要做成通用的,每个父组件调用下筛选的UI,岂不是很傻。

于是在面临这种既有UI的复用,又有逻辑的复用,hooks 就难以处理了,还是用 render props 来处理。

如下是实现的一个简易自定义列组件。

/*
 * @File: 自定义表格列
 * @Author: nsne
 * @Date: 2020-01-03 15:08:32
 * @Last Modified by: nsne
 * @Last Modified time: 2020-01-03 17:16:30
 * @Usage
 *
      <CustomColumn columns={props.columns}>
        {(columns: ColumnProps<any>[]) => (
          <Table
            className={`${styles.mTaskTable} ${className}`}
            expandRowByClick
            expandedRowKeys={expandedRowKeys}
            onExpandedRowsChange={onExpandedRowsChange}
            {...restProps}
            columns={columns}
          />
        )}
      </CustomColumn>
*
 */
import React, { useState, useEffect } from 'react';
import { Popover, Button, Checkbox } from 'antd';
import { ColumnProps } from 'antd/lib/table';
import _ from 'lodash';
import styles from './index.less';

const CustomColumn = (props: {
  columns: ColumnProps<any>[];
  defaultColumns?: Array<ColumnProps<any> | string>;
  children: (columns) => React.ReactNode;
}) => {
  const { columns = [] } = props;
  const [column, setColumn] = useState(columns);
  const onChange = value => {
    const { columns = [] } = props;
    const column = columns.filter(
      item => value.includes(item.dataIndex) || value.includes(item.title),
    );
    setColumn(column);
  };

  let { defaultColumns = [] } = props;
  useEffect(() => {
    defaultColumns = defaultColumns?.length ? defaultColumns : columns;
    const defaultValue = defaultColumns
      .map(item => (typeof item === 'string' ? item : item?.dataIndex || _.toString(item?.title)))
      .filter(item => column.some(cell => cell.dataIndex === item || cell.title === item));
    onChange(defaultValue);
  }, []);

  const renderContent = () => (
    <Checkbox.Group
      options={columns?.map((item: ColumnProps<any>, index) => ({
        label: item.title || '',
        value: item.dataIndex || _.toString(item.title) || index,
      }))}
      value={column.map(item => item.dataIndex || _.toString(item.title))}
      onChange={onChange}
    />
  );

  return (
    <div className={styles.cCustomColumn}>
      <Popover
        content={renderContent()}
        title="请选择要展示的列名"
        trigger="click"
        overlayClassName={styles.mCustomPopover}
      >
        <Button icon="setting">自定义列</Button>
      </Popover>
      {props.children(column)}
    </div>
  );
};

export default CustomColumn;

NsNe
1.7k 声望38 粉丝

善良,学习,拼搏。不忘初心,方得始终。