Skip to content

9.18 笔记

项目整理 对editProTale再次封装

场景1 实现逐行增加功能,以及自定义操作列

描述

INFO

现在存在一种场景,我需要逐行进行增加,并且对操作列和表格展示页面进行自定义,具体设计如下

思路

  1. 需要明确的是,原本的操作列是没法满足按行增加这个功能的,所以只能自己手写
    1. 那么就需要明确,react是根据状态来进行渲染的,要想视图产生编辑和查看的状态,那么就需要处理好这两种状态
    2. 编辑:editableKeys,只有key在editableKeys这个数组里,那么才会出现编辑的状态
    3. 保存:处理好value

官网描述:

  1. value:同dataSource,传入一个数组,是ttable渲染的元数据
  2. editableKeys:正在编辑的行,受控属性。 默认key 会使用rowKey 的配置,如果没有配置会使用index,建议使用rowKey
  1. 对于操作列的的自定义,我们可以直接在**actionRender**自定义操作栏里面使用
    1. 它里面提供了三个方法:保存,取消,删除
    2. 但是如果你自定义的操作栏里想要调用它,他们只能
javascript
const editable = {
  // defaultDom = {save,cancel,delete} 可以酌情添加和使用
  actionRender: (row, config, defaultDom) => [
    defaultDom.save,
    defaultDom.cancel,
  ],
};
3. **但是如果你需要的不仅仅是这个,那么你也可以在这个里面写一些**`**HTML**`**元素,****但是,这就带来,你所需要的方法你需要方法封装**
jsx
actionRender: (row, config, dom) => {
  return [
    <Button type="primary" shape="circle" icon={<PlusCircleOutlined />} onClick={() => addItem(row)} key={"addEditTable-add"} />,
    <Button type='primary' shape='circle' icon={<CheckCircleOutlined />} onClick={() => savaItem(row)} key={"addEditTable-confirm"}></Button>,
    <Popconfirm
      title="删除"
      onConfirm={() => deleteItem(row)}
      okText="Yes"
      cancelText="No"
      key={"addEditTable-delete"}
    >
    <Button type="primary" shape="circle" icon={<MinusCircleOutlined />} key={"addEditTable-delete-btn"} disabled={dataSource.length === 1} />
  </Popconfirm>,
]
}
}}

代码

jsx
/**
 * @description 借助editProTable实现的,可以单行新增,删除,编辑的操作的组件
 */
const AddEditTable: React.FC<AddEditTableProps> = (props) => {
  const { editableFormRef } = props
  // 设置默认数据
  const defaultData = setAddThreeCodeValue({gunNum:1})
  // editableKeys 用于控制哪些行可以编辑,要求所有的都可以编辑,所以map一下,取出所有的id
  const [editableKeys, setEditableRowKeys] = useState<React.Key[]>(defaultData.map((item) => item.id));
  const [dataSource, setDataSource] = useState<IThreeCodeBindingAddTableColumns[]>([]);

  // 新增行操作
  const addItem = (record:IThreeCodeBindingAddTableColumns) => {
    // 设置新增数据
    const newData = setAddThreeCodeValue({gunNum:1})[0];
    // 找到当前的index,后续需要在index后面增加
    const index = dataSource.findIndex((item) => item.id === record.id);
    setDataSource(mergeEmptyToDataSource(dataSource,newData,index))
    // 将新增的数据的id添加到editableKeys中
    setEditableRowKeys([...editableKeys, newData.id]);
  }
  // 删除行数据
  const deleteItem = (record: IThreeCodeBindingAddTableColumns) => {
    setDataSource(dataSource.filter((item) => item.id !== record.id));
    setEditableRowKeys(editableKeys.filter((item) => item !== record.id))
  }
  // 更新行数据
  const updateItem = (record: IThreeCodeBindingAddTableColumns[]) => {
    setDataSource(record);
    // 将他们设置为可编辑状态
    setEditableRowKeys(record.map((item) => item.id));
  }
  return (
    <EditableProTable
      columns={setColumns({ deleteItem, addItem, savaItem, dataSource, selectedRow, updateItem })}
      rowKey="id"
      value={dataSource} // table渲染的元数据
      loading={false}
      onChange={setDataSource} //当dataSource变化时,将dataSource的id赋值给editableKeys
      recordCreatorProps={false}// 不展示新增按钮
      // 编辑行的配置
      editable={{
        type: 'multiple',
        editableKeys,
        onChange: setEditableRowKeys,
        // 自定义编辑行的操作
        actionRender: (row, config, dom) => {
          return [
            <Button type="primary" shape="circle" icon={<PlusCircleOutlined />} onClick={() => addItem(row)} key={"addEditTable-add"} />,
            <Button type='primary' shape='circle' icon={<CheckCircleOutlined />} onClick={() => savaItem(row)} key={"addEditTable-confirm"}></Button>,
            <Popconfirm
              title="删除"
              onConfirm={() => deleteItem(row)}
              okText="Yes"
              cancelText="No"
              key={"addEditTable-delete"}
            >
            <Button type="primary" shape="circle" icon={<MinusCircleOutlined />} key={"addEditTable-delete-btn"} disabled={dataSource.length === 1} />
          </Popconfirm>,
          ]
      }
   }}
    // table的ref
    editableFormRef={editableTableRef}
  />
  )
};

export default AddEditTable;

参考链接

  1. EditProTable API
  2. 表格 Table - Ant Design

场景2 编辑态展示

描述

INFO

编辑态展示的不是只读的描述列表,而是一个不可编辑的input

思路

  1. 其实就像上面写的那样,就需要我们自己去进行render,我们就需要借助两个属性renderFormItemrender

官网描述:

  1. renderFormInstance:可以自定义编辑组件

  1. render:生成复杂数据的渲染函数

代码

jsx
export const setAddThreeCodeColumn = (dataSource: IThreeCodeBindingAddTableColumns[], updateItem: any): ProColumns<IThreeCodeBindingAddTableColumns>[] => {
  return [
    // 省略一些没用的类定义
    {
      title: '终端SN',
      dataIndex: 'terminalSn',
      renderFormItem(schema: any, config, form, action) {
        let type = 1;
        return <Input onPressEnter={(e) => pressTerminalSn({ e, dataSource, schema, updateItem, type })} />
        }
    },
    // 省略
    },
    {
      title: "枪数",
      dataIndex: "gunNum",
      // TODOS:如果和当前操作的terminalSn相同的话,那么才需要设置小锁,否则不需要设置小锁
      renderFormItem(schema: any, config, form, action) {
        let type = 1;
        return (
          <Input type="number" defaultValue={0} onPressEnter={(e) => { pressGunNum({ e, dataSource, schema, updateItem, type }) }}
         suffix={<UnlockOutlined onClick={() => changeLockStatus({ schema, dataSource, updateItem })} style={{ color: 'black' }} />}
      disabled={schema.entity?.status}
          />
    )
    },
  },
 // 省略
  {
    title: "操作",
    valueType: 'option',
  }
];
}

场景3 单独设置编辑态

描述

INFO

表格的枪数这一列,我们需要对他的状态进行一个单独的设置,设置一个小锁,来表示他的开闭状态

思路

  1. 对于状态的管理,在react中,会很容易想到去设置一个单独的状态,来管理这个开闭状态
  2. 但是因为,目前的场景比较特殊:
    1. 小锁打开,那么对应的和他的sn相同的产品的小锁也要打开
    2. 并且当前这个小锁的开闭状态不会影响到其他无关的产品
  3. 这时候你如果使用state来进行管理的话,那么就比较困难,简单来说,就是很难做到唯一性
  4. 对于有一定条件下,或者唯一性的时候,其实最好让数据自己去管理自己内部的状态
  5. 简单来说就是:我们可以对这一行数据设置**state**,然后小锁根据自己的**state**来显示开闭状态
  6. 后续当我们改变某一个状态的时候,只需要遍历**dataSource**让和他们相同的**sn**的状态全部取反就可以了

代码

jsx
{
  title: "枪数",
    dataIndex: "gunNum",
    // TODOS:如果和当前操作的terminalSn相同的话,那么才需要设置小锁,否则不需要设置小锁
    renderFormItem(schema: any, config, form, action) {
    let type = 1;
    return (
      <Input type="number" defaultValue={0} onPressEnter={(e) => { pressGunNum({ e, dataSource, schema, updateItem, type }) }}
     suffix={<UnlockOutlined onClick={() => changeLockStatus({ schema, dataSource, updateItem })} style={{ color: 'black' }} />}
    disabled={schema.entity?.status}
   />
  )
},
jsx
export const changeLockStatus = ({schema,dataSource,updateItem}:IChangeLockStatus) => {
  // 将dataSource中的terminalSn和当前的terminalSn进行比较,如果相同的话,那么就设置小锁
  dataSource.forEach((item) => {
    if (item.terminalSn === schema.entity.terminalSn) {
      item.status = !item.status;
    }
  })
  // 更新dataSource
  updateItem(dataSource);
}