考试周回到学校反而有时间整理实习期间的随笔
第一种思路是以功能为聚合,例如点击按钮弹出模态框的话那么就写一个按钮组件,这种思路的优点是在一处进行管理功能,用到的时候只需要将按钮嵌入页面就好,但是可能没法在同一处管理某页面用到的所有模态框
第二种思路就是通过钩子函数内部对模态框的状态进行管理,那么外部调用只需要调用方法即可
在内部管理状态用到了Reducer统一管理多种模态框时的action、state
// 模态框状态类型
interface ModalState {
qrcodeDetail: {
visible: boolean;
mode: 'edit' | 'create';
data: QrCodeRecord | null;
};
docConfig: {
visible: boolean;
};
qrcodeView: {
visible: boolean;
imgUrl: string;
};
}
// Action 类型定义
type ModalAction =
| { type: 'SHOW_QRCODE_DETAIL'; mode: 'edit' | 'create'; data?: QrCodeRecord }
| { type: 'CLOSE_QRCODE_DETAIL' }
| { type: 'SHOW_DOC_CONFIG' }
| { type: 'CLOSE_DOC_CONFIG' }
| { type: 'SHOW_QRCODE_VIEW'; imgUrl: string }
| { type: 'CLOSE_QRCODE_VIEW' };
// 初始状态
const initialModalState: ModalState = {
qrcodeDetail: {
visible: false,
mode: 'create',
data: null,
},
docConfig: {
visible: false,
},
qrcodeView: {
visible: false,
imgUrl: '',
},
};
// Reducer 函数
const modalReducer = (state: ModalState, action: ModalAction): ModalState => {
switch (action.type) {
case 'SHOW_QRCODE_DETAIL':
return {
...state,
qrcodeDetail: {
visible: true,
mode: action.mode,
data: action.data || null,
},
};
case 'CLOSE_QRCODE_DETAIL':
return {
...state,
qrcodeDetail: {
visible: false,
mode: 'create',
data: null,
},
};
case 'SHOW_DOC_CONFIG':
return {
...state,
docConfig: {
visible: true,
},
};
case 'CLOSE_DOC_CONFIG':
return {
...state,
docConfig: {
visible: false,
},
};
case 'SHOW_QRCODE_VIEW':
return {
...state,
qrcodeView: {
visible: true,
imgUrl: action.imgUrl,
},
};
case 'CLOSE_QRCODE_VIEW':
return {
...state,
qrcodeView: {
visible: false,
imgUrl: '',
},
};
default:
return state;
}
};
// 弹窗管理Hook
export const useModals = (handleSuccess?: () => void) => {
const [state, dispatch] = useReducer(modalReducer, initialModalState);
const showEditModal = (mode: 'edit' | 'create', record?: QrCodeRecord) => {
dispatch({ type: 'SHOW_QRCODE_DETAIL', mode, data: record });
};
const closeEditModal = () => {
dispatch({ type: 'CLOSE_QRCODE_DETAIL' });
};
const showConfigModal = () => {
dispatch({ type: 'SHOW_DOC_CONFIG' });
};
const closeConfigModal = () => {
dispatch({ type: 'CLOSE_DOC_CONFIG' });
};
const showViewModal = (qrCodeUrl: string) => {
dispatch({ type: 'SHOW_QRCODE_VIEW', imgUrl: qrCodeUrl });
};
const closeViewModal = () => {
dispatch({ type: 'CLOSE_QRCODE_VIEW' });
};
const modalHandlers = {
onShowEditModal: showEditModal,
onShowViewModal: showViewModal,
onShowConfigModal: showConfigModal,
};
const modals = (
<>
{state.qrcodeDetail.visible && (
<QrcodeDetailModal
formData={state.qrcodeDetail.data}
mode={state.qrcodeDetail.mode}
onClose={closeEditModal}
onSuccess={() => {
handleSuccess?.();
closeEditModal();
}}
visible={state.qrcodeDetail.visible}
/>
)}
{state.docConfig.visible && (
<DocConfigModal
onClose={closeConfigModal}
onSuccess={() => {
handleSuccess?.();
}}
visible={state.docConfig.visible}
/>
)}
{state.qrcodeView.visible && (
<QrcodeViewModal
onClose={closeViewModal}
qrcodeImgUrl={state.qrcodeView.imgUrl}
visible={state.qrcodeView.visible}
/>
)}
</>
);
return {
modalHandlers,
modals,
};
};
还可以进一步简化,从打开和关闭维度看只有两个action,只不过打开和关闭的是不同的模态框,即不同的ModalState中的Key。
export const useModals = (handleSuccess?: () => void) => {
const [state, dispatch] = useReducer(modalReducer, initialModalState);
const show = (key: ModalKey, payload?: any) =>
dispatch({ type: 'SHOW', key, payload });
const close = (key: ModalKey) => dispatch({ type: 'CLOSE', key });
const modalHandlers = {
onShowEditModal: (mode: 'edit' | 'create', data?: QrCodeRecord) =>
show('qrcodeDetail', { mode, data }),
onShowConfigModal: () => show('docConfig'),
onShowViewModal: (imgUrl: string) => show('qrcodeView', { imgUrl }),
};
const modals = (
<>
{state.qrcodeDetail.visible && (
<QrcodeDetailModal
formData={state.qrcodeDetail.data}
mode={state.qrcodeDetail.mode}
onClose={() => close('qrcodeDetail')}
onSuccess={() => {
handleSuccess?.();
close('qrcodeDetail');
}}
visible
/>
)}
{state.docConfig.visible && (
<DocConfigModal
onClose={() => close('docConfig')}
onSuccess={handleSuccess}
visible
/>
)}
{state.qrcodeView.visible && (
<QrcodeViewModal
onClose={() => close('qrcodeView')}
qrcodeImgUrl={state.qrcodeView.imgUrl}
visible
/>
)}
</>
);
return { modalHandlers, modals };
};
后续如果还想添加页面只需要在ModalState、initialModalState以及钩子内部的modalHandlers中、JSX部分加就好