内容简介:在 web 上经常看到包含一个或多个日期的表单。无论是出生日期还是航班时间表日期,您总希望用户能够提供了有效的日期。在 HTML5 中,引入了新的您可以在
在 web 上经常看到包含一个或多个日期的表单。无论是出生日期还是航班时间表日期,您总希望用户能够提供了有效的日期。
在 HTML5 中,引入了新的 date 输入类型,来确保获取表单中的有效日期值。 date 输入类型的默认行为是向用户显示日期选择器。但是,这个日期选择器的外观在不同浏览器之间并不一致。
您可以在 这里 找到更多关于 date 输入类型和浏览器支持的信息。
在本教程中,您将学习如何使用 React 和原生 JavaScript日期对象从头构建自定义日期选择器。下面是一个简短的演示,展示了日期选择器的外观。
您还可以在 Code Sandbox 上查看 演示 。
先决条件
本教程假设您非常熟悉 JavaScript,并且已经熟悉 React 框架。如果不是这样,您可以查看 React文档 来了解有关React的更多信息。
在开始之前,您需要确保您的计算机上已经安装了 Node 。建议您在机器上安装 Yarn 包管理器,因为它将代替 Node 附带的 npm 。您可以按照此 Yarn 安装指南 在您的机器上安装 Yarn。
React 应用程序的样板代码将使用 create-react-app 包创建。您还需要确保它在您的机器上是全局安装的。如果您使用 npm >= 5.2 ,那么您不需要将 create-react-app 作为一个全局依赖项安装——您可以使用 npx 命令。
开始
创建新的应用程序
使用以下命令创建新的 React 应用程序。您可以随意命名应用程序。
create-react-app react-datepicker
npm> = 5.2 如果您使用的是 npm 5.2 或更高版本,它会附带一个额外的 npx 二进制文件。 使用 npx 二进制文件,您无需在计算机上全局安装 create-react-app 。 您可以使用以下简单命令创建新的 React 应用程序:
npx create-react-app react-datepicker
安装依赖
这个应用程序的依赖尽可能地保持精简。运行以下命令安装所需的依赖项。
yarn add bootstrap reactstrap styled-components prop-types
引入 Bootstrap CSS
本教材为了方便,直接使用 bootstrap 来提供一些默认样式。请编辑 src/index 并在其他 import 语句之前添加以下行。
import 'bootstrap/dist/css/bootstrap.min.css';
目录设置
对于这个应用程序,需要两个主要组件。
Calendar组件 Datepicker组件
每个组件都将包含在自己的目录中,其中包含两个文件—— index.js 和 styles.js 。 index.js 导出组件,而 styles.js 导出组件所需样式的样式化组件。
从项目根目录运行以下命令来创建组件目录和文件:
# Create directories mkdir -p src/components/Calendar src/components/Datepicker # Create files (cd src/components/Calendar && touch index.js styles.js) (cd src/components/Datepicker && touch index.js styles.js)
由于在这个应用程序中不需要外部依赖来处理日期,因此需要自己编写日期处理的 helper 函数。运行以下命令来创建 calendar helper 模块。
mkdir -p src/helpers touch src/helpers/calendar.js
启动应用程序
通过在终端上使用 yarn 运行以下命令来启动应用程序:
yarn start
应用程序现在已经启动,可以开始开发了。请注意,已经为您打开了一个浏览器选项卡,该选项卡具有实时重新加载功能,以便在开发时与应用程序中的更改保持同步。
Calendar helper 模块
基本常量和 helper 函数
首先,定义一些构建日历所需的日历常量和 helper 函数。它们将在前面创建的 calendar helper 模块中定义并导出。
将以下内容添加到 src/helpers/calendar.js 文件中。
// (int) The current year
export const THIS_YEAR = +(new Date().getFullYear());
// (int) The current month starting from 1 - 12
// 1 => January, 12 => December
export const THIS_MONTH = +(new Date().getMonth()) + 1;
// Week days names and shortnames
export const WEEK_DAYS = {
Sunday: "Sun",
Monday: "Mon",
Tuesday: "Tue",
Wednesday: "Wed",
Thursday: "Thu",
Friday: "Fri",
Saturday: "Sat"
}
// Calendar months names and shortnames
export const CALENDAR_MONTHS = {
January: "Jan",
February: "Feb",
March: "Mar",
April: "Apr",
May: "May",
June: "Jun",
July: "Jul",
August: "Aug",
September: "Sep",
October: "Oct",
November: "Nov",
December: "Dec"
}
// Weeks displayed on calendar
export const CALENDAR_WEEKS = 6;
// Pads a string value with leading zeroes(0) until length is reached
// For example: zeroPad(5, 2) => "05"
export const zeroPad = (value, length) => {
return `${value}`.padStart(length, '0');
}
// (int) Number days in a month for a given year from 28 - 31
export const getMonthDays = (month = THIS_MONTH, year = THIS_YEAR) => {
const months30 = [4, 6, 9, 11];
const leapYear = year % 4 === 0;
return month === 2
? leapYear
? 29
: 28
: months30.includes(month)
? 30
: 31;
}
// (int) First day of the month for a given year from 1 - 7
// 1 => Sunday, 7 => Saturday
export const getMonthFirstDay = (month = THIS_MONTH, year = THIS_YEAR) => {
return +(new Date(`${year}-${zeroPad(month, 2)}-01`).getDay()) + 1;
}
这个代码片段包含注释,解释每个 helper 函数都做了什么。然而,有几件事值得指出。
首先, Date.prototype 中的 getDay() 和 getMonth() 方法通常会返回从零开始的值。因此,一年的第一个月(January)是 0 ,December 是 11 ,而一周的第一天(Sunday)是 0 ,Saturday 是 7 。
在前面的代码片段中,您会看到 1 总是被添加到这些从零开始的值中,因此 Sunday 为 1 ,December 为 12 。
还要注意, CALENDAR_WEEKS 被设置为 6 。由于一个月通常跨越 4 周,因此日历至少可以容纳上个月的最后一周和下个月的第一周。您很快就会看到这个常量的效果,因为它将在 calendar builder 函数中使用。
额外的 helper 函数
将以下内容附加到 src/helper/calendar.js 文件中,添加一些额外的辅助功能到 calendar helper 模块。
// (bool) Checks if a value is a date - this is just a simple check
export const isDate = date => {
const isDate = Object.prototype.toString.call(date) === '[object Date]';
const isValidDate = date && !Number.isNaN(date.valueOf());
return isDate && isValidDate;
}
// (bool) Checks if two date values are of the same month and year
export const isSameMonth = (date, basedate = new Date()) => {
if (!(isDate(date) && isDate(basedate))) return false;
const basedateMonth = +(basedate.getMonth()) + 1;
const basedateYear = basedate.getFullYear();
const dateMonth = +(date.getMonth()) + 1;
const dateYear = date.getFullYear();
return (+basedateMonth === +dateMonth) && (+basedateYear === +dateYear);
}
// (bool) Checks if two date values are the same day
export const isSameDay = (date, basedate = new Date()) => {
if (!(isDate(date) && isDate(basedate))) return false;
const basedateDate = basedate.getDate();
const basedateMonth = +(basedate.getMonth()) + 1;
const basedateYear = basedate.getFullYear();
const dateDate = date.getDate();
const dateMonth = +(date.getMonth()) + 1;
const dateYear = date.getFullYear();
return (+basedateDate === +dateDate) && (+basedateMonth === +dateMonth) && (+basedateYear === +dateYear);
}
// (string) Formats the given date as YYYY-MM-DD
// Months and Days are zero padded
export const getDateISO = (date = new Date) => {
if (!isDate(date)) return null;
return [
date.getFullYear(),
zeroPad(+date.getMonth() + 1, 2),
zeroPad(+date.getDate(), 2)
].join('-');
}
// ({month, year}) Gets the month and year before the given month and year
// For example: getPreviousMonth(1, 2000) => {month: 12, year: 1999}
// while: getPreviousMonth(12, 2000) => {month: 11, year: 2000}
export const getPreviousMonth = (month, year) => {
const prevMonth = (month > 1) ? month - 1 : 12;
const prevMonthYear = (month > 1) ? year : year - 1;
return { month: prevMonth, year: prevMonthYear };
}
// ({month, year}) Gets the month and year after the given month and year
// For example: getNextMonth(1, 2000) => {month: 2, year: 2000}
// while: getNextMonth(12, 2000) => {month: 1, year: 2001}
export const getNextMonth = (month, year) => {
const nextMonth = (month < 12) ? month + 1 : 1;
const nextMonthYear = (month < 12) ? year : year + 1;
return { month: nextMonth, year: nextMonthYear };
}
Default export
最后,这里是 calendar helper 模块的默认导出—— calendar builder 函数 。该函数以 month 和 year 作为参数,并返回一个包含 42 个元素的数组,每个元素以 [YYYY, MM, DD] 的格式表示日历日期。
下面是 calendar builder 函数。将此代码段追加到 src/helper/calendar.js 文件。
// Calendar builder for a month in the specified year
// Returns an array of the calendar dates.
// Each calendar date is represented as an array => [YYYY, MM, DD]
export default (month = THIS_MONTH, year = THIS_YEAR) => {
// Get number of days in the month and the month's first day
const monthDays = getMonthDays(month, year);
const monthFirstDay = getMonthFirstDay(month, year);
// Get number of days to be displayed from previous and next months
// These ensure a total of 42 days (6 weeks) displayed on the calendar
const daysFromPrevMonth = monthFirstDay - 1;
const daysFromNextMonth = (CALENDAR_WEEKS * 7) - (daysFromPrevMonth + monthDays);
// Get the previous and next months and years
const { month: prevMonth, year: prevMonthYear } = getPreviousMonth(month, year);
const { month: nextMonth, year: nextMonthYear } = getNextMonth(month, year);
// Get number of days in previous month
const prevMonthDays = getMonthDays(prevMonth, prevMonthYear);
// Builds dates to be displayed from previous month
const prevMonthDates = [...new Array(daysFromPrevMonth)].map((n, index) => {
const day = index + 1 + (prevMonthDays - daysFromPrevMonth);
return [ prevMonthYear, zeroPad(prevMonth, 2), zeroPad(day, 2) ];
});
// Builds dates to be displayed from current month
const thisMonthDates = [...new Array(monthDays)].map((n, index) => {
const day = index + 1;
return [year, zeroPad(month, 2), zeroPad(day, 2)];
});
// Builds dates to be displayed from next month
const nextMonthDates = [...new Array(daysFromNextMonth)].map((n, index) => {
const day = index + 1;
return [nextMonthYear, zeroPad(nextMonth, 2), zeroPad(day, 2)];
});
// Combines all dates from previous, current and next months
return [ ...prevMonthDates, ...thisMonthDates, ...nextMonthDates ];
}
请注意,calendar builder 在数组中返回的日历日期从上一个月最后一周的日期到给定月份的日期,再到下一个月第一周的日期。
以上所述就是小编给大家介绍的《如何使用 React 构建自定义日期选择器(1)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 使用Python构建自定义新闻源
- 使用rpmbuild自定义构建rpm包
- 使用CSS自定义属性构建骨架屏
- 如何使用 React 构建自定义日期选择器(3)
- 如何使用 React 构建自定义日期选择器(2)
- 重新定义堡垒机 构建IT基础设施特权身份银行
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
机器与人:埃森哲论新人工智能
【美】保罗•多尔蒂 詹姆斯•威尔逊 / 赵亚男 / 中信出版社 / 2018-10-1 / 49.00元
自人工智能问世以来,人们普遍持有人机对立的观点,且无时无刻不在害怕自己的工作会被人工智能取代。作者认为,是时候抛开这些无谓的担忧了,因为人类社会正走向一个与机器共融共生的时代。 未来的新型工作模式是什么?未来有哪些工作不会被人工智能取代?人工智能时代重要的生存技能是什么?本书围绕这三大核心问题做了透彻的分析。作者带我们见识了置于业务流程背景之下的人工智能,阐述了其在不同职能部门中起到的推动作......一起来看看 《机器与人:埃森哲论新人工智能》 这本书的介绍吧!
URL 编码/解码
URL 编码/解码
Markdown 在线编辑器
Markdown 在线编辑器