React 横向日期选择器:优雅处理日期选择与业务逻辑

72 阅读3分钟

本文将详细解析一个基于 React 和 Ant Design 的横向日期选择器组件,展示如何构建一个既美观又实用的日期选择功能。

组件概述

这是一个横向滚动的日期选择器组件,具有以下特点:

  • 横向布局:日期水平排列,支持滚动查看整月日期
  • 月份切换:可向前后切换月份
  • 智能禁用:根据当前时间自动禁用未来日期
  • 选中状态:清晰显示当前选中日期
  • 响应式设计:适配不同屏幕尺寸

核心代码解析

1. 状态管理

const [currentDate, setCurrentDate] = useState(moment());
const [selectedDate, setSelectedDate] = useState(moment());

组件使用两个状态:

  • currentDate:控制当前显示的月份
  • selectedDate:记录用户选择的日期

2. 日期数据处理

// 获取当前月份的所有日期
const getDaysInMonth = () => {
  const startDate = currentDate.clone().startOf('month');
  const endDate = currentDate.clone().endOf('month');
  const days = [];
  
  let day = startDate.clone();
  while (day.isSameOrBefore(endDate)) {
    days.push(day.clone());
    day.add(1, 'day');
  }
  
  return days;
};

这个方法使用 moment.js 生成当前月份的所有日期数组,为渲染日期列表提供数据。

3. 智能日期禁用逻辑

const isDisabled = (day) => {
  const now = moment()
  const currentHour = now.hours()
  if (currentHour < 21) {
    return day && (day > moment().endOf('day'))
  } else {
    return day && (day > moment().add(1, 'day').endOf('day'))
  }
};

这是一个非常实用的业务逻辑:根据当前时间决定禁用规则:

  • 21点前:只能选择当天及之前的日期
  • 21点后:可以选择明天及之前的日期

这种设计常见于预约、订餐等需要提前准备的业务场景。

4. 月份切换功能

// 切换月份
const changeMonth = (increment) => {
  setCurrentDate(currentDate.clone().add(increment, 'month'));
};

通过简单的 moment.js 操作实现月份切换,支持向前后导航。

5. 日期选择处理

// 处理日期点击
const handleDateClick = (day) => {
  setSelectedDate(day);
  dateChange(day)
};

选择日期时更新内部状态并通过回调函数通知父组件,实现数据双向流动。

组件 UI 设计

布局结构

<div style={{ 
  width: '100%',
  maxWidth: '100%',
  overflowX: 'auto',
  padding: '16px 0'
}}>
  {/* 月份导航和日期列表 */}
  <div style={{ 
    display: 'flex',
    flexDirection: 'row',
    alignItems: 'center',
    gap: '8px',
    padding: '0 8px'
  }}>
    {/* 月份切换按钮 */}
    {/* 月份显示 */}
    {/* 日期滚动区域 */}
    {/* 月份切换按钮 */}
  </div>
</div>

日期项样式设计

<div 
  style={{
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'center',
    minWidth: '40px',
    padding: '8px 4px',
    borderRadius: '4px',
    background: isSelected(day) ? '#e6f7ff' : 'transparent',
    color: isSelected(day) ? '#1890ff' : '#333',
    fontWeight: isSelected(day) ? 'bold' : 'normal',
    cursor: disabled ? 'not-allowed' : 'pointer',
    opacity: disabled ? 0.4 : 1,
    transition: 'all 0.2s',
  }}
>
  {/* 星期几 */}
  {/* 日期数字 */}
</div>

使用示例

import HorizontalDateSlider from './HorizontalDateSlider';

const MyComponent = () => {
  const handleDateChange = (selectedDate) => {
    console.log('选择的日期:', selectedDate.format('YYYY-MM-DD'));
    // 执行相关业务逻辑
  };
  
  return (
    <div>
      <HorizontalDateSlider 
        dateChange={handleDateChange}
      />
    </div>
  );
};

优化建议

  1. 性能优化:对于日期计算可以使用 useMemo 缓存
  2. 可访问性:添加键盘导航支持
  3. 国际化:支持多语言星期显示
  4. 自定义样式:通过 props 允许自定义主题色等样式

总结

这个横向日期选择器组件展示了如何在 React 中:

  • 处理复杂的日期逻辑
  • 实现优雅的 UI 交互
  • 集成业务规则(如时间相关的禁用逻辑)
  • 保持组件的可复用性

通过合理的状态设计和业务逻辑封装,该组件既满足了基本功能需求,又具备了良好的扩展性。


关注我的稀土掘金账号,获取更多前端开发实战技巧和组件设计思路!