html5 自定义 datepicker,如何使用 React 构建自定义日期选择器(3)

本文作者:IMWeb howenhuo

未经同意,禁止转载

Datepicker 组件

构建 Datepicker 组件

要开始构建 Datepicker 组件,请将以下代码片段添加到 src/components/Datepicker/index.js 文件。

import React from "react";

import PropTypes from "prop-types";

import Calendar from "../Calendar";

import * as Styled from "./styles";

import { isDate, getDateISO } from "../../helpers/calendar";

class Datepicker extends React.Component{

state = { date: null, calendarOpen: false }

toggleCalendar = () => this.setState({ calendarOpen: !this.state.calendarOpen })

handleChange = evt => evt.preventDefault()

handleDateChange = date => {

const { onDateChanged } = this.props;

const { date: currentDate } = this.state;

const newDate = date ? getDateISO(date) : null;

currentDate !== newDate &&

this.setState({ date: newDate, calendarOpen: false }, () => {

typeof onDateChanged === "function" && onDateChanged(this.state.date);

});

}

componentDidMount() {

const { value: date } = this.props;

const newDate = date && new Date(date);

isDate(newDate) && this.setState({ date: getDateISO(newDate) });

}

componentDidUpdate(prevProps) {

const { value: date } = this.props;

const { value: prevDate } = prevProps;

const dateISO = getDateISO(new Date(date));

const prevDateISO = getDateISO(new Date(prevDate));

dateISO !== prevDateISO && this.setState({ date: dateISO });

}

}

Datepicker.propTypes = {

label: PropTypes.string,

value: PropTypes.string,

onDateChanged: PropTypes.func

}

export default Datepicker;

在这里,组件 state 初始化为两个属性:

date:一个 ISO string,表示日期选择器的当前日期。格式是 “YYYY-MM-DD”。

calendarOpen :一个 boolean 标记,表示日期选择器的日历是否可见。

当组件 mount 时,Date 对象从传递给组件 props 的 value 解析,并更新 state,如componentDidMount() 方法所示。

handleDateChange() 方法以 Date 对象作为参数,并更新 state 下的 date。如果 Datepicker 组件的 props 传递了 onDateChanged 回调函数,则将使用更新的 ISO 日期字符串调用该函数。

渲染 datepicker

此时,值得一提的是,Bootstrap Dropdown 组件将用于模拟自定义日期选择器的下拉效果。这就是为什么 Reactstrap 包被添加为此项目的依赖项的原因。

正如您很快会注意到,在日期选择器中渲染的样式化组件是 Reactstrap 下拉组件的样式扩展。

更新 Datepicker 组件以包含 render() 方法,如下面的代码片段所示。

class Datepicker extends React.Component {

// ... other methods here

render() {

const { label } = this.props;

const { date, calendarOpen } = this.state;

return (

{label || 'Enter Date'}

type="text"

value={date ? date.split("-").join(" / ") : ""}

onChange={this.handleChange}

readOnly="readonly"

placeholder="YYYY / MM / DD"

/>

{ calendarOpen && (

)}

);

}

}

Styled.DatePickerFormGroup 组件是一个 Bootstrap 的 .form-group,它包装日期选择器标签和输入字段。需要注意的是,输入字段的类型是 “text”,并且标记为 readonly,这样就无法直接编辑它。还要注意,输入元素上的 change 事件的默认行为已经被阻止。

Styled.DatePickerDropdown 组件及其后代,是 Reactstrap 包 Dropdown 组件的样式扩展。您可以在 这里 了解更多关于 Reactstrap 下拉列表的信息。

最后,Calendar 组件在下拉菜单中渲染,传递 state 中的 date 和 onDateChanged 回调函数的handleDateChange() 方法。

Datepicker 组件最终渲染的 DOM 应该如下所示(带有一些样式):

719bc9310051a06d8016e8633e3eb0fc.png

设置日期选择器的样式

将以下代码片段添加到 src/components/Datepicker/styles.js,以创建日期选择器所需的样式组件。

import styled from 'styled-components';

import { FormGroup, Label, Input, Dropdown, DropdownToggle, DropdownMenu } from 'reactstrap';

export const DatePickerContainer = styled.div`

position: relative;

`;

export const DatePickerFormGroup = styled(FormGroup)`

display: flex;

justify-content: space-between;

position: relative;

width: 100%;

border: 2px solid #06c;

border-radius: 5px;

overflow: hidden;

`;

export const DatePickerLabel = styled(Label)`

margin: 0;

padding: 0 2rem;

font-weight: 600;

font-size: 0.7rem;

letter-spacing: 2px;

text-transform: uppercase;

color: #06c;

border-right: 2px solid #06c;

display: flex;

align-items: center;

justify-content: center;

background: rgba(0, 102, 204, 0.05);

`;

export const DatePickerInput = styled(Input)`

padding: 1rem 2rem;

font-weight: 500;

font-size: 1rem;

color: #333;

box-shadow: none;

border: none;

text-align: center;

letter-spacing: 1px;

background: transparent !important;

display: flex;

align-items: center;

::placeholder {

color: #999;

font-size: 0.9rem;

}

`;

export const DatePickerDropdown = styled(Dropdown)`

position: absolute;

width: 100%;

height: 100%;

top: 0;

left: 0;

`;

export const DatePickerDropdownToggle = styled(DropdownToggle)`

position: relative;

width: 100%;

height: 100%;

background: transparent;

opacity: 0;

filter: alpha(opacity=0);

`;

export const DatePickerDropdownMenu = styled(DropdownMenu)`

position: absolute;

top: 0;

left: 0;

width: 100%;

border: none;

padding: 0;

margin: 0;

transform: none !important;

`;

应用程序组件

最后,更新 src/App.js 文件,看起来像下面的代码片段。

import React, { Component } from "react";

import Datepicker from "./components/Datepicker";

class App extends Component {

render() {

return (

);

}

}

export default App;

如果您按照本文和代码片段进行操作,则应该在 React 应用程序中渲染出一个可用的自定义日期选择器。

结论

在本教程中(1、2、3),您已经能够逐步了解如何构建一个定制的 React 日期选择器组件,该组件可以作为原生 HTML5 日期选择器输入元素的替代。

虽然本教程中创建的自定义日期选择器能按预期工作,但它并不能完全满足日期选择器元素的所有要求。可以进一步改进,例如:

通过 props 实现 max 和 min 日期

将输入类型从 “text” 切换到 “date”

更好的可访问性改进

你可以在 react-datepicker-demo 的 GitHub 上获得这个自定义日期选择器的更多改进版本的完整源代码。 您还可以在 Code Sandbox 上查看演示。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值