前言
页面我用一个Modal组件包一个Form组件,由于页面较复杂,所以采用混合布局,一部分用Form.Item包裹组件(受控),一部分直接用原始组件(不受控)
受 控 组 件 :手动改变,页面动态更新,form.getFieldsValue() 能取到最新值
不受控组件:
- 设置defaultValue时,手动改变,页面动态更新,onChange能取到输入的值,外部数据也更新 【√】
- 设置value时,手动改变,页面不能更新,onChange能取到输入的值,外部数据也更新【×】
新建操作:不受控组件用defaultValue,没什么问题
查看操作:需要根据保存的数据,进行表单赋值。由于Modal关闭后没有销毁里面的组件,我的defaultValue还是上一次的值,再次打开Modal,数据不能进行更新
需要在Modal关闭后重置表单或销毁组件,打开后重新渲染
- 重置表单,因为页面大部分是不受控的组件,不能用
form.reset
来重置 【×】 - 销毁组件 【√】
如何销毁组件?
- Modal组件有个 destroyOnClose属性,介绍说是Modal关闭后销毁里面的组件,加了后不生效 【×】
- 给组件添加一个key值,当需要更新的时候,添加一个新的key值,组件就会重新渲染,原理为React的Diff算法 【√】
Modal组件destroyOnClose属性,如何使用才能生效?
(可以试一下,我没试过)
核心代码
useEffect(() => {
// 如果选中班次有值,查看操作,渲染值
if (kqbc.gdbz.activeBc) {
window.key = Date.now();
renderFormData(kqbc.gdbz.activeBc);
}
}, [modalVisible]);
<Form ... key={window.key} />
const XjbcModal = (props) => {
const [bcCount, setBcCount] = useState(1); // 上下班次数
const [kqfs, setKqfs] = useState(1); // 考勤方式 (1,2) => (固定时间考勤,弹性考勤)
const [xxsjCheck, setXxsjCheck] = useState(false); // 开启休息时间
...
useEffect(() => {
// 如果选中班次有值,渲染值
if (kqbc.gdbz.activeBc) {
window.key = Date.now();
renderFormData(kqbc.gdbz.activeBc);
}
}, [modalVisible]);
const renderFormData = (id) => {
...
form.setFieldsValue({
bcmc: target.bcmc, // 班次名称
sxbcs: target.bc.length, // 上下班次数
kqfs: target.kqfs, // 考勤方式
sbsj: moment(target.bc[0].sbsj, 'HH:mm'), // 上班时间
xbsj: moment(target.bc[0].xbsj, 'HH:mm'), // 下班时间
});
flexDefaultTime.sbbtqksj = target.bc[0].sbbtqksj; // 上班晚到半天缺卡时间
flexDefaultTime.zzsbdk = moment(target.bc[0].zzsbdk, 'HH:mm'); // 最早打卡上班时间
flexDefaultTime.xbbtqksj = target.bc[0].xbbtqksj; // 下班早退半天缺卡时间
flexDefaultTime.zwxbdk = moment(target.bc[0].zwxbdk, 'HH:mm'); // 最晚打卡下班时间
flexDefaultTime.sbwdh = target.bc[0].sbwdh; // 上班晚到小时
...
}
...
const renderWorktimeContainer = () => {
...
<Col>
<Form.Item ... initialValue={flexDefaultTime.sbsj}>
<TimePicker ... />
</Form.Item>
</Col>
<Col>
<div>
晚到超过
<InputNumber
...
defaultValue={flexDefaultTime.sbbtqksj}
// value={flexDefaultTime.sbbtqksj}
onChange={(value) => flexDefaultTime.sbbtqksj = value}
/>
分钟记为半天缺卡
</div>
<div>
最早
<TimePicker
...
defaultValue={flexDefaultTime.zzsbdk}
// value={flexDefaultTime.zzsbdk}
onChange={(value) => flexDefaultTime.zzsbdk = value}
/>
打卡上班
</div>
</Col>
...
}
return (
<>
<Modal>
<Form ... key={window.key}>
<Form.Item ...>
<Input ... />
</Form.Item>
...
<Row>
<Col>工作时长:9小时0分钟</Col>
{ renderWorktimeContainer() }
</Row>
<Collapse>
<Collapse.Panel>
...
</Collapse.Panel>
</Collapse>
</Form>
</Modal>
</>
)
}
export default connect(({ kqgz }) => ({ kqgz }) )(XjbcModal);
const options = [
{ label: '1次上下班', value: 1 },
{ label: '2次上下班', value: 2 },
{ label: '3次上下班', value: 3 },
];
// 固定时间考勤 - 默认上下班时间段
const defaultTime = [
{sbsj: moment('09:00', 'HH:mm'), xbsj: moment('11:30', 'HH:mm'), sbcdsj: 0, sbbtqksj: 30, tqdksj: 60, xbztsj: 0, xbbtqksj: 30, yhdksj: 60},
{sbsj: moment('13:30', 'HH:mm'), xbsj: moment('17:30', 'HH:mm'), sbcdsj: 0, sbbtqksj: 30, tqdksj: 30, xbztsj: 0, xbbtqksj: 30, yhdksj: 60},
{sbsj: moment('19:30', 'HH:mm'), xbsj: moment('20:00', 'HH:mm'), sbcdsj: 0, sbbtqksj: 30, tqdksj: 30, xbztsj: 0, xbbtqksj: 30, yhdksj: 480},
];
// 弹性考勤 - 默认上下班时间段
const flexDefaultTime = {
sbsj: moment('09:00', 'HH:mm'), // 上班时间
xbsj: moment('18:00', 'HH:mm'), // 下班时间
sbbtqksj: 60, // 上班晚到半天缺卡时间
zzsbdk: moment('07:00', 'HH:mm'), // 最早打卡上班时间
xbbtqksj: 60, // 下班早退半天缺卡时间
zwxbdk: moment('02:00', 'HH:mm'), // 最晚打卡下班时间
sbwdh: 1, // 上班晚到小时
sbwdm: 0, // 上班晚到分钟
xbzth: 1, // 下班早退小时
xbztm: 0 // 下班早退分钟
};