最近公司项目有需求,要在日期选择框内剔除非交易日,将非交易日置灰不可选。查了一下 antd 的 DatePicker 中可以用 disabledDate 属性来控制,但这个属性 must be a function,否则会报错,let me simple try try now。
disabledDate = current => current < moment();
rander(){
return (
<DatePicker
format="YYYY-MM-DD"
disabledDate={this.disabledDate}
/>
)
}
但这只是个 Demo,完全不符合公司需求。公司需求是剔除非交易日。非交易日大致包括所有周六周日与法定节假日,这里取值不是前端做的,是后端小哥哥给的接口,查询的数据库。格式是这样的:
[......, '2020-05-13', '2020-05-14', '2020-05-15', '2020-05-16', ......]
在这里,后端小哥哥给了我交易日的列表从 1990 年开始到现在,这个数组长度大约 7300 多,如果把这些数据代入进 DatePicker,那么会出现一个问题,就是点击与改变 DatePicker 的值的时候(onClick and onChange),会卡半天。我的电脑是 8代i5+12G+256 的,年代距今大约 2 年,电脑本身计算这点东西应该不会有性能问题,窃以为应该是 antd 本身的问题,导致计算次数过多,电脑忙不过来了。
所以需要在调用接口之后,获取的 res 当中处理一下。本身查看未来数据这是不可能的,因为还没发生的交易是没有数据的。查看过去的数据,没必要从 1990 年开始,我详细和产品同学探讨了一下,最终产品决定从3年前的1月1日开始至今的日期范围内,可以供用户选择。在此我筛选了一下,如下
balabala接口调用.then (res => {
const dateList = _.filter(res, item => moment(item).isBetween('2018-01-01', moment().format('YYYY-MM-DD'), 'day', '[]'));
this.setState({
tradingDat: dateList
});
}
对上面写法的一下解释:
_.filter : lodash 库中的一个方法,可以当做 filter 封装后的方法。
moment(xxx).isBetween(xxxx, xxxx, xxxx, xxxx) : moment.js 提供的一个方法,详情请见 momentjs.cn/docs/#/quer…, 通过不同的传参来设置不同的筛选条件,在 moment.js 官网有详细的解释,下官网首页上方导航栏内点击“文档”,进入查看。 比如最后一个参数有这几种'()'、'[]'、'(]'、'[)',分别代表对筛选调节边界的判断(包含或不包含)。
现在重头戏来了,怎样将数据代入 DatePicker 中进行渲染? 毫不夸张的说,也不怕各位笑话,我在这步上,总共花了一晚上加一上午。
具体因为啥呢?想来想去应该是格式问题,我就此开始专攻格式,进行了各种 demo test。直接说结果吧,现在我要禁用 5月5/6/7 三个日子,
像下面这样的效果:
function disabledDate(current) {
const { dateList } = this.state;
// dateList的格式是这样的:[......, "2020-05-05", "2020-05-06", "2020-05-07", ......];
// 是从后端接口中获取的值
// 下面开始进行筛选,将筛选值作为return返出去
return dateList.some(item => {
// 也可以不用moment(item)来转化格式,因为item的格式已经是'YYYY-MM-DD'了
const date = moment(item);
// 但是必须把current格式转化一下,在这个方法 (this.disabledDate) 里面打印current是没有结果显示的,我试验了一晚上,各种方法都不行
// 肯定是格式原因,那么我将它也转成'YYYY-MM-DD'格式去比较,果然可以。
const currentDate = moment(current).format("YYYY-MM-DD");
return date.isSame(currentDate);
}) || current < moment('2018-01-01') || current > moment();
}
好了,实现了。下面解释一下上面代码
return some() 中的 return 中,isSame() 函数是 moment.js 提供的方法,用来判断前一个时间和后一个时间是否一致的,文档在此:momentjs.cn/docs/#/quer… 格式应该是 这样的
moment(xxxx).isSame(xxxx),
意在判断前一个 xxxx 和后一个 xxxx 是否一致。
最后两 “||” 判断,是将除了3年内日期以外的日期全部禁用掉。
还有一种情况,数据库中的数据只有“交易日”,没法查询非交易日怎么办,这就涉及到取反。注意:不要在 some 内的 return 上取反,直接在整个方法的 return中取反,如下:
true:
disableDate = current => {
const { 日期列表 } = this.state;
return !日期列表.some(item => {
const currentDate = moment(current).format('YYYY-MM-DD');
return item === curentDate;
}) || current > moment() || current < moment('2018-01-01')
}
false:
disableDate = current => {
const { 日期列表 } = this.state;
return 日期列表.some(item => {
const currentDate = moment(current).format('YYYY-MM-DD');
return item !== curentDate;
}) || current > moment() || current < moment('2018-01-01')
}
好了,大功告成,完毕。
就这么个小东西,我搜遍全网都没找到,也怪自己菜,淌水淌了一晚加一上午。