Antd Modal + ProTble 封装高复用性增删改modal组件

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
感谢阅读,欢迎批评指正,希望大家能够在追求卓越中不断进步,让优秀成为一种习惯~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值