antd v3 select自定义下拉框内容失去焦点时会关闭下拉框

antd 版本 3.19.3 先说一下我遇到的问题,项目中需要做多日期对比,本来想使用 DatePicker 组件,每次选择一个日期,感觉这样写太过简单,于是,就想结合 SelectCalendar 组件一起使用,想法是很美好的,操作起来就困难重重了,我想要的效果如下图:

采用的是Select 的中 dropdownRender自定义下拉框内容,但是自定义内容中包含Select的话就会因失去焦点而关闭,无法选择,查了很多资料,都说如下方法可以解决,试了很多次都无效,于是就换了一种写法,自己写一个类似Select的组件不就行了,于是就选择了Dropdown

javascript 复制代码
<Select
  dropdownRender={() => (
    <div
      onMouseDown={(e) => {
        e.preventDefault();
        e.stopPropagation();
      }}
    >
      Some Content
    </div>
  )}
/>

对于 Calendar组件,要使用dateFullCellRender,重新单元格,方便添加选中样式,只需要稍微修改一下样式就可以了。

css 复制代码
// CalendarPage.css
.my_calendar .ant-fullcalendar-cell .ant-fullcalendar-selected-day .ant-fullcalendar-value {
  color: #fff !important;
  background: #1677ff !important;
}

.my_calendar .ant-fullcalendar-cell.ant-fullcalendar-selected-day .ant-fullcalendar-value {
  color: unset;
  background: unset;
}

.my_calendar_menu {
  max-height: 300px;
  overflow: auto;
}

Calendar组件二次封装

javascript 复制代码
import React from 'react';
import { Calendar, Card, Row, Col, Menu, Dropdown, Button } from 'antd'
import { DownOutlined } from '@ant-design/icons'
import moment from 'moment'
import './CalendarPage.css'
const dateFormat = 'YYYY-MM-DD'
export default function CalendarPage(props) {
  const { values, handleSelect, ...resProps } = props
  return (
    <Card
      bodyStyle={{ padding: 0, width: 300 }}
      onMouseDown={e => {
        e.preventDefault()
      }}
      style={{ width: 300 }}
    >
      <Calendar
        headerRender={({ value, type, onChange, onTypeChange }) => {
          const start = 0
          const end = 12
          const monthOptions = []
          const current = value.clone()
          const localeData = value.localeData()
          const months = []
          for (let i = 0; i < 12; i++) {
            current.month(i)
            months.push(localeData.monthsShort(current))
          }
          for (let index = start; index < end; index++) {
            monthOptions.push(
              <Menu.Item className="month-item" key={`${index}`}>
                {months[index]}
              </Menu.Item>
            )
          }
          const month = value.month()
          const year = value.year()
          const options = []
          for (let i = year - 10; i < year + 10; i += 1) {
            options.push(
              <Menu.Item key={i} value={i} className="year-item">
                {i}
              </Menu.Item>
            )
          }
          const menu = (
            <Menu
              size="small"
              onClick={newYear => {
                const now = value.clone().year(newYear.key)
                onChange(now)
              }}
              className="my_calendar_menu"
            >
            	{options}
            </Menu>
          )
          const menu2 = (
            <Menu
              size="small"
              onClick={selectedMonth => {
                const newValue = value.clone()
                newValue.month(parseInt(selectedMonth.key, 10))
                onChange(newValue)
              }}
              className="my_calendar_menu"
            >
            	{monthOptions}
            </Menu>
          )
          return (
            <div style={{ padding: 10 }}>
              <Row type="flex" justify="end">
                <Col>
                  <Dropdown size="small" overlay={menu}>
                    <Button>
                      {String(year)}
                      <DownOutlined />
                    </Button>
                  </Dropdown>
                </Col>
                <Col>
                  <Dropdown size="small" overlay={menu2}>
                    <Button style={{ marginLeft: 10 }}>
                      {months[month]}
                      <DownOutlined />
                    </Button>
                  </Dropdown>
                </Col>
              </Row>
            </div>
          )
        }}
        fullscreen={false}
        className="calendar"
        dateFullCellRender={date => {
          let de = moment(date).format(dateFormat)
          let cls = ''
          if (values && values.indexOf(de) !== -1) {
            cls = 'ant-fullcalendar-selected-day'
          } else {
            cls = ''
          }
          return (
            <div
              className={cls}
              onClick={() => {
                handleSelect && handleSelect(moment(date).format(dateFormat))
              }}
            >
              <div className="ant-fullcalendar-value" style={{ textAlign: 'center' }}>
                {moment(date).date()}
              </div>
            </div>
          )
        }}
        {...resProps}
      />
    </Card>
  )
}

使用

javascript 复制代码
import CalendarPage from './CalendarPage'
<Select
  dropdownRender={() => (
      <CalendarPage
      	handleSelect={e=>{
      		// 逻辑处理,动态设置values
      	}
      	values={['2023-06-01', '2023-06-25']}
      />
  )}
/>
相关推荐
子兮曰2 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰2 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万2 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝2 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋2 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁2 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95272 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大2 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师2 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学2 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端