在开发中需要使用到年份的选择器,由于项目使用的是 Antd3.0 版本,在查看文档后发现并没有可以直接使用的组件,并且在项目的多个地方需要使用到,就打算基于 DatePicker 写一个 YearPicker 组件。
首先在 DatePicker 组件中有一个 mode 属性
该属性控制面板的状态,我们选择使用 year 来让面板显示年份。
只有这个属性是远远不够的,如果要实现选择年份的功能,我们还需要手动控制选择器的弹窗显示,选中后的回调等等。
那么就要用到这两个属性
onOpenChange 的使用就很简单了
const [isopen, setIsOpen] = useState<boolean>(false);
const handleOpenChange = (status: boolean) => {
setIsOpen(status)
};
定义一个 isopen 来控制年份选择面板显示和隐藏,当触发 handleOpenChange 方法,直接将 status 赋值给 isopen 即可。
而 handlePanelChange 方法就是我们用来拿到选择年份并处理的方法了,
// 拿到 value 并进行处理,给 YearPicker 组件赋值
const handlePanelChange = (value: any) => {
setIsOpen(false);
// value 可能是父组件传来的值,也可能是操作组件选择的年份值,需要变为 moment 对象再给组件赋值
const momentYear = moment(value, 'YYYY');
// 返回给父组件的值为格式化的值
const yearFormat = moment(momentYear).format('YYYY');
// 组件只接受 moment 对象的值
setYear(momentYear);
handleChange(Number(yearFormat));
};
首先该方法拿到的参数可能是我们选择年份面板取到的值,也可能是我们在父组件中需要进行初始化而传来的值,由于组件的 value 只接受 moment 对象的值,所以在赋值之前,先用 moment 转换一下。
这里需要注意的是,第二个参数指定转换的格式,我们需要将年份转换成 moment 对象,所以是 'YYYY'
然后我们拿到值后进行两个操作,一个是给组件赋值,一个是将年份传给父组件进行使用,这里的 handleChange 方法是通过父组件传过来的取到值后进行的操作。
到这里一个简单的 YearPicker 组件差不多就写好了,我们还可以在对其进行稍微加工。
首先,该组件如果使用在搜索表单中,那他可能会需要一个清除的功能,这里我们使用 onChange 方法搭配 allowClear 属性。
当点击清除触发 onChange 方法,直接将组件和父组件的值重新设置。
const handleChanges = (date: any) => {
setYear(date);
handleChange(date);
};
最后将 handleChanges、handlePanelChange 方法抛出给父组件,这里使用 useImperativeHandle + forwardRef 方法。
useImperativeHandle(ref, () => ({
handleChanges,
handlePanelChange,
}));
完整代码
function YearPicker({ handleChange, allowClear = true }: IProps, ref: any) {
const [year, setYear] = useState<Moment>();
const [isopen, setIsOpen] = useState<boolean>(false);
const handleOpenChange = (status: boolean) => {
setIsOpen(status)
};
// 拿到 value 并进行处理,给 YearPicker 组件赋值
const handlePanelChange = (value: any) => {
setIsOpen(false);
// value 可能是父组件传来的值,也可能是操作组件选择的年份值,需要变为 moment 对象再给组件赋值
const momentYear = moment(value, 'YYYY');
// 返回给父组件的值为格式化的值
const yearFormat = moment(momentYear).format('YYYY');
// 组件只接受 moment 对象的值
setYear(momentYear);
handleChange(Number(yearFormat));
};
const handleChanges = (date: any) => {
setYear(date);
handleChange(date);
};
// 传递给父组件 change 方法
useImperativeHandle(ref, () => ({
handleChanges,
handlePanelChange,
}));
return (
<DatePicker
mode="year"
placeholder="请选择年份"
open={isopen}
format="YYYY"
value={year}
onOpenChange={handleOpenChange}
onPanelChange={handlePanelChange}
onChange={handleChanges}
style={{ width: '100%' }}
allowClear={allowClear}
/>
);
}
export default forwardRef(YearPicker);