Antd Modal + ProTble 封装高复用性增删改modal组件
写在前面:
这篇文章偏向分享,就当是为像笔者这样的Antd Pro beginner抛砖引玉吧,如果大神能提出指导或者建议,笔者不胜感激!
Let’s check them out !
一、全局控制Modal的显现
src/model/globalModel.js
const GlobalModel = {
namespace: 'GlobalModel',
state: {
createModalVisible: false, // 创建使用的Modal
createDetailModalVisible: false, // 创建详情使用的Modal
modifyModalVisible: false, // 修改使用的Modal
modifyDetailModalVisible: false, // 修改详情使用的Modal
deleteModalVisible: false, // 删除使用的Modal
deleteDetailModalVisible: false, // 删除详情使用的Modal
currentRowData :{}
},
effects: {},
reducers: {
changeCreateModalVisible(state, action) { // 改变modalVisible的状态,以下都是这个套路
return { ...state, createModalVisible: action.payload };
},
changeCreateDetailModalVisible(state, action) {
return { ...state, createDetailModalVisible: action.payload };
},
changeModifyModalVisible(state, action) {
return { ...state, modifyModalVisible: action.payload };
},
changeModifyDetailModalVisible(state, action) {
return { ...state, modifyDetailModalVisible: action.payload };
},
changeDeleteModalVisible(state, action) {
return { ...state, deleteModalVisible: action.payload };
},
changeDeleteDetailModalVisible(state, action) {
return { ...state, deleteDetailModalVisible: action.payload };
},
saveCurrentRowData(state, action) { // 保存用户当前正在修改的那一条属性
return { ...state, currentRowData: action.payload };
},
},
};
export default GlobalModel;
做这一步封装呢,是因为笔者之前为了业务,在各个页面下创建大量的useState来控制modal的显现,终于导致自己一时不查,凑齐七个useState,召唤了神龙(莫名其妙的Bug),于是痛定思痛,抽离出来,作为公共的state。
问题:这么做虽然会很大程度上减少代码量,但是每次modal显现的时候都会导致页面小刷新,降低性能,这一点笔者暂时没有想到很好的解决方案,元芳,你怎么看?
二、封装全局的父组件Modal
@/components/CreateInfoModal/index.jsx
import React from 'react';
import { Modal } from 'antd';
const CreateInfoModal = props => {
const { modalVisible, onCancel,title } = props;
return (
<Modal
destroyOnClose
title={title}
visible={modalVisible}
onCancel={() => onCancel()}
footer={null}
maskClosable = {false}
{...props} // 增加更多自定义的功能
>
{props.children}
</Modal>
);
};
export default CreateInfoModal;
这个其实没啥可说的,其实就是将Antd Modal在封装一层,根据笔者的业务需求增加一些固定的属性即可。
三、封装增、删、改Modal
@/components/CreateModal
import React from 'react'
import CommonModal from '@/components/createInfoModal'; // 上文封装好的通用modal
import ProTable from '@ant-design/pro-table';
import {connect} from 'umi'
const CreateModal = props => {
const { columns, title, createModalVisible } = props
// columns : 让ProTable 生成相应的form表单
// title : Modal的title
// createModalVisible:全局控制的创建Modal显现
const { dispatch, onSubmit } = props
return (
<CommonModal
title={title} onCancel={
() => {
dispatch({
type: "GlobalModel/changeCreateModalVisible",
payload: false
})
}
}
modalVisible={createModalVisible}
>
<ProTable
onSubmit={async (value) => {
await onSubmit(value) // 调用提交创建的函数
dispatch({
type: "GlobalModel/changeCreateModalVisible",
payload: false
}) // 关闭modal
}}
rowKey="id"
type="form"
columns={columns}
/>
</CommonModal>
)
}
export default connect(({ GlobalModel }) => ({
createModalVisible: GlobalModel.createModalVisible,
}))(CreateModal)
@/components/DeleteModal/index.jsx
import React from 'react'
import CommonModal from '@/components/createInfoModal';
import {connect} from 'umi'
import globalStyles from '@/global.less';
import { Button } from 'antd'
const DeleteModal = props => {
const { deleteModalVisible, dispatch, deleteFunc, title } = props
return (
<CommonModal
title={title}
onCancel={() => {
dispatch({
type: "GlobalModel/changeDeleteModalVisible",
payload: false
})
}} modalVisible={deleteModalVisible}>
<p>是否确认删除</p> // 这里笔者就设置的比较简单,更多的是提示作用,如果大家还需要其它内容可以自行更改
<div className={globalStyles.flexCenter}>
<Button type="primary" onClick={async () => {
await deleteFunc()
dispatch({
type: "GlobalModel/changeDeleteModalVisible",
payload: false
}) // 关闭删除modal
}} >确认删除</Button>
</div>
</CommonModal>
)
}
export default connect(({ GlobalModel }) => ({
deleteModalVisible: GlobalModel.deleteModalVisible,
}))(DeleteModal)
@/components/DeleteModal/index.jsx
import React from 'react'
import CommonModal from '@/components/createInfoModal';
import ProTable from '@ant-design/pro-table';
import { connect } from 'umi'
const ModifyModal = props => {
const { modifyColumns, title, modifyModalVisible, modifyRef, currentRowData } = props
// modifyRef : 用来调用 ProTable 上的setFieldsValue来实现填充
// currentRowData : 当前用户正在修改的那一条属性
const { dispatch, onSubmit } = props
return (
<CommonModal
title={title}
onCancel={() => {
dispatch({
type: "GlobalModel/changeModifyModalVisible",
payload: false
})
}} modalVisible={modifyModalVisible}>
<ProTable
onSubmit={async value => {
const params = Object.assign(currentRowData,value)
// 将用户修改的内容覆盖掉原来的那一条属性,并保留没有修改的内容
await onSubmit(params)
dispatch({
type: "GlobalModel/changeModifyModalVisible",
payload: false
})
}}
rowKey="id"
type="form"
columns={modifyColumns}
formRef={modifyRef}
/>
</CommonModal>
)
}
export default connect(({ GlobalModel }) => ({
modifyModalVisible: GlobalModel.modifyModalVisible,
currentRowData: GlobalModel.currentRowData
}))(ModifyModal)
四、实际使用(以UserManage页面为例)
columns.js
export const columns = (postValueEnum, roleValueEnum, sexValueEnum, statusValueEnum, options) => {
return [
{
title: '用户名',
dataIndex: 'username',
rules: [
{
required: true,
message: '此项为必填项',
},
]
},
。。。 省略大家知道意思就好
];
};
export const modifyColumns = (postValueEnum, roleValueEnum, sexValueEnum, statusValueEnum) => {
return [
{
title: '用户名',
dataIndex: 'username',
},
{
title: '真实姓名',
dataIndex: 'realname',
},
。。。 省略大家知道意思就好
];
}
笔者这里是把columns从页面中抽离出来,当作函数或者变量来使用,减少页面代码量。
index.jsx
<CreateUserModal
title="新建用户"
columns={columns(postValueEnum, roleValueEnum, sexValueEnum, statusValueEnum, options)}
onSubmit={createUserFunc} // 自定义的创建函数,大家如果需要的话可以看笔者的源码
/>
<ModifyUserModal
title="修改用户"
modifyColumns={modifyColumns(postValueEnum, roleValueEnum, sexValueEnum, statusValueEnum)}
modifyRef={modifyRef}
onSubmit={handleUpdate}
/>
<DeleteUserModal
title="删除用户"
deleteFunc={deleteUserFunc}
/>
export default connect(({ UserManageModel }) => ({
currentResetUser: UserManageModel.currentResetUser
}))(UserManage)
然后给大家对比一下愚蠢的笔者之前写的代码。。。。
<CreateRole
title="新建角色" onCancel={() => {
dispatch({
type: "GlobalModel/changeCreateModalVisible",
payload: false
})
}} modalVisible={createModalVisible}>
<ProTable
onSubmit={async value => {
let success = await createRoleFunc(value);
if (success) {
dispatch({
type: "GlobalModel/changeCreateModalVisible",
payload: false
})
if (actionRef.current) {
actionRef.current.reload();
}
}
}}
rowKey="createUser"
type="form"
columns={columns}
/>
</CreateRole>
<CreateRole
title="修改角色"
onCancel={() => {
dispatch({
type: "GlobalModel/changeModifyModalVisible",
payload: false
})
}} modalVisible={modifyModalVisible}>
<ProTable
onSubmit={async value => {
console.log("value", value)
let params = { ...value, id: currentRowData.id }
await handleUpdate(params);
}}
rowKey="id"
type="form"
columns={modifyColumns}
formRef={modifyRef}
/>
</CreateRole>
export default connect(({ CharManageModel, loading, GlobalModel }) => ({
createModalVisible: GlobalModel.createModalVisible, // modal重复引入
modifyModalVisible: GlobalModel.modifyModalVisible,
deleteModalVisible: GlobalModel.deleteModalVisible,
currentModifyRole: GlobalModel.currentModifyRole,
currentRowData: GlobalModel.currentRowData
}))(CharManage)
好了。。不多说了,talk is cheap,show me the code。。。大家细品吧。。。
源码地址:https://github.com/aoyinke/antdPro_menuAuth
感谢阅读,欢迎批评指正,希望大家能够在追求卓越中不断进步,让优秀成为一种习惯~