9.18 笔记
项目整理 对editProTale再次封装
场景1 实现逐行增加功能,以及自定义操作列
描述
INFO
现在存在一种场景,我需要逐行进行增加,并且对操作列和表格展示页面进行自定义,具体设计如下
思路
- 需要明确的是,原本的操作列是没法满足按行增加这个功能的,所以只能自己手写
- 那么就需要明确,react是根据状态来进行渲染的,要想视图产生编辑和查看的状态,那么就需要处理好这两种状态
- 编辑:
editableKeys
,只有key在editableKeys
这个数组里,那么才会出现编辑的状态 - 保存:处理好
value
官网描述:
value
:同dataSource,传入一个数组,是
ttable渲染的元数据editableKeys
:正在编辑的行,受控属性。 默认key 会使用rowKey 的配置,如果没有配置会使用index,建议使用rowKey
- 对于操作列的的自定义,我们可以直接在
**actionRender**
自定义操作栏里面使用- 它里面提供了三个方法:保存,取消,删除
- 但是如果你自定义的操作栏里想要调用它,他们只能
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;
参考链接
场景2 编辑态展示
描述
INFO
编辑态展示的不是只读的描述列表,而是一个不可编辑的input
思路
- 其实就像上面写的那样,就需要我们自己去进行
render
,我们就需要借助两个属性renderFormItem
和render
官网描述:
renderFormInstance
:可以自定义编辑组件
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
表格的枪数这一列,我们需要对他的状态进行一个单独的设置,设置一个小锁,来表示他的开闭状态
思路
- 对于状态的管理,在
react
中,会很容易想到去设置一个单独的状态,来管理这个开闭状态 - 但是因为,目前的场景比较特殊:
- 小锁打开,那么对应的和他的
sn
相同的产品的小锁也要打开 - 并且当前这个小锁的开闭状态不会影响到其他无关的产品
- 小锁打开,那么对应的和他的
- 这时候你如果使用
state
来进行管理的话,那么就比较困难,简单来说,就是很难做到唯一性 - 对于有一定条件下,或者唯一性的时候,其实最好让数据自己去管理自己内部的状态
- 简单来说就是:我们可以对这一行数据设置
**state**
,然后小锁根据自己的**state**
来显示开闭状态 - 后续当我们改变某一个状态的时候,只需要遍历
**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);
}