仿Antd组件之DatePicker组件实现(简易)

发表于 2022-03-11 757 字 4 min read

心得

  • 契机是什么才不说呢
  • 也算是第一次用 React 写自己的小组件,可能封装性还不行,bug 也还有不少,写的代码自己复盘的时候也很想吐槽 2333
  • 不过也真的是个很有意思的事!比如点击日期选择器外关闭日期选择器这个功能就纠结了我好长时间 qwq,但是写完真的很快乐!
  • 使用了 React 的来 ref 判断点击事件发生在组件内部还是外部~
  • 实现自己的组件是很 cool 的事!虽然有时候也会感觉有点重复造轮子
  • 在学习 antd 组件的实现同时也感受到了其实现的不少细节,望尘莫及 ovo,以后有机会还会有优化哒,增加更多 api 和功能和自定义大小设置等。

组件介绍

DatePicker 组件

DatePicker 组件开发 代码及在线预览地址:DatePicker(by cos)

  1. 日、月、年选择面板的实现 交互: a.日面板实现:实现点击日期选择具体日期,点击头部面部左右箭头可前往上一年/下一年、上一月/下一月 b.月面板实现:点击日面板头部月份进入,点击月份则选择具体月份并返回日面板,点击头部面部左右箭头前往上一年/下一年 c.年面板实现:点击日面板头部月份进入,以十年为区间,点击年份则选择该年并返回日面板,点击头部面部左右箭头前往上个十年/下个十年 d.根据输入框输入实时变换日期
  2. 对外 API 的实现 a. 支持默认日期的设置 defaultDate 通过设置 defaultDate 为 moment 对象实现默认日期的设置 b. 支持日期的获取 onDateChange 通过日期变化的回调函数获取当前日期,返回 moment 对象 示例:
class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      nowDate: 'No Value!',
    };
  }
  handleDateChange(date) {
    this.setState({ nowDate: date.format('YYYY-MM-DD') });
  }
  render() {
    return (
      <div className="App">
        <div>nowDate: {this.state.nowDate}</div>
        <DatePicker defaultDate={moment()} onDateChange={(date) => this.handleDateChange(date)} />
      </div>
    );
  }
}
  1. 面板展示与切换动画 通过 picker-panel 中初始透明度 opacity为 0,变化原点transform-origin为左上角,初始大小为 scale(0) ,通过自定义属性 data-active 为 true 控制显示
.picker-panel {
  z-index: 10;
  position: absolute;
  background-color: white;
  top: 30px;
  left: 0;
  width: 300px;
  height: 300px;
  border-radius: 3px;
  border: 1px solid $gray-4;
  box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.4);

  display: flex;
  flex-direction: column;

  opacity: 0;
  transform: scale(0);
  transform-origin: top left;
  transition: all 300ms ease-in-out;
  &[data-active='true'] {
    transform: scale(1);
    opacity: 1;
  }
}
  1. 界面展示
  • 初始值

初始值.png

  • 选择其他日期 选择其他日期.png

  • 下一年 下一年.png

  • 上一个月 上一个月.png

  • 进入年面板 进入年面板.png

  • 切换年面板 切换年面板.png

  • 月面板

月面板.png