说明

个人娱乐所写,UI方面参照其他人的UI设计

支持功能

初始化日期

高亮'今天'以及选择日期

历史记录选择日期

支持tag标识

支持选择日期回调

支持上一月/下一月选择回调

支持tags动态切换

屏幕适应

效果图

基本思路

计算出这一年中的每个月对应的天数,其中需要根据年份来判断2月份到底是28天还是29天,使用数组保存

计算出这个月的第一天是星期几,来决定前面应该会有多少上个月的空格以及根据天数来判断月后应该有多少天来弥补

渲染思路:

使用三个数组,分别存有上一个月、当前月以及下一个月应该渲染的天数

数组合并,根据每一行应该显示7列的特性,将大数组划分为6个小数组,这6个小数组中即为每一行应该显示的星期数

具体代码

/**

* Created by Ryn on 2016/8/7.

* 日历组件

*/

import React from 'react';

import H from '../helpers/H';

const Calendar = React.createClass({

/**

* 默认的属性

*/

getDefaultProps() {

return {

row_number : 6,

col_number : 7

}

},

/**

* 组件初始化状态

*/

getInitialState() {

return {

current_year : H.getFullYear(),

current_month : H.getMonth(),

current_day : H.getDate(),

select_year : H.getFullYear(),

select_month : H.getMonth(),

select_day : H.getDate(),

history_year : undefined,

history_month : undefined,

history_day : undefined,

date_num_array : []

}

},

componentWillReceiveProps(nextProps) {

// todo

},

/**

* 组件渲染完后执行

*/

componentDidMount() {

let { year, month, day} = this.props;

// 初始化状态

if(year && month && day) {

let date_num_array = this._initMonthDayNumber(year),

first_day = H.weekOfMonth(new Date(year, month - 1));

this.setState({

select_year : year,

select_month : month - 1,

select_day : day,

date_num_array : date_num_array,

first_day : first_day

});

}

},

/**

* 给月份数组附上每月天数

* @param year 年份

* @private

*/

_initMonthDayNumber(year) {

let _date_array = [];

for (var i = 0; i < 12; i++) {

switch (i + 1) {

case 1:

case 3:

case 5:

case 7:

case 8:

case 10:

case 12:

_date_array.push(31);

break;

case 4:

case 6:

case 9:

case 11:

_date_array.push(30);

break;

case 2:

if (H.isLeapYear(year)) {

_date_array.push(29);

} else {

_date_array.push(28);

}

break;

default:

break;

}

}

return _date_array;

},

/**

* 组件将要挂载

* 设置月份数组以及计算出每月的第一天星期几

*/

componentWillMount() {

let date_num_array = this._initMonthDayNumber(this.state.current_year),

first_day = H.weekOfMonth();

this.setState({date_num_array : date_num_array, first_day : first_day});

},

/**

* 日期选择

* @param s_day

*/

selectDate(s_day) {

let { select_year, select_month} = this.state;

this.setState({

history_year : select_year,

history_month : select_month,

history_day : s_day,

select_day : s_day

}, () => {

this.props.onSelectDate(select_year, select_month + 1, s_day);

});

},

/**

* 前一个月

*/

previousMonth() {

let { current_year, current_month, current_day,

select_year, select_month, select_day, date_num_array, first_day} = this.state;

if (select_month === 0) {

select_year = +select_year - 1;

select_month = 11;

date_num_array = this._initMonthDayNumber(select_year);

} else {

select_month = +select_month - 1;

}

first_day = H.weekOfMonth(new Date(select_year, select_month));

if (current_year === select_year &&

current_month === select_month) {

select_day = current_day;

} else {

select_day = undefined;

}

this.setState({

select_year : select_year,

select_month : select_month,

select_day : select_day,

date_num_array : date_num_array,

first_day : first_day

})

},

/**

* 之后一个月

*/

nextMonth() {

let { current_year, current_month, current_day,

select_year, select_month, select_day, date_num_array, first_day} = this.state;

if (select_month === 11) {

select_year = +select_year + 1;

select_month = 0;

date_num_array = this._initMonthDayNumber(select_year);

} else {

select_month = +select_month + 1;

}

first_day = H.weekOfMonth(new Date(select_year, select_month));

if (current_year === select_year &&

current_month === select_month) {

select_day = current_day;

} else {

select_day = undefined;

}

this.setState({

select_year : select_year,

select_month : select_month,

select_day : select_day,

date_num_array : date_num_array,

first_day : first_day

})

},

/**

* 渲染页面

* @returns {XML}

*/

render() {

let { row_number, col_number, tags } = this.props;

let { current_year, current_month, current_day,

select_year, select_month, select_day,

history_year, history_month, history_day,

date_num_array, first_day} = this.state;

let month_day = date_num_array[select_month],

n_day = row_number * col_number - first_day - month_day,

previous_month_days = undefined,

previous_days = [],

current_days = [],

next_days = [],

total_days = [],

previous_month = undefined;

if (select_month === 0) {

previous_month = 11;

} else {

previous_month = select_month - 1;

}

previous_month_days = date_num_array[previous_month];

for (let i = 0; i < first_day; i++) {

let previous_link = (

{previous_month_days - (first_day - i) + 1}

);

previous_days.push(previous_link);

}

let currentClassName = '',

currentText = '';

for (let i = 0; i < month_day; i++) {

// 今天样式

if (current_year == select_year && current_month == select_month && current_day == (i + 1)) {

currentClassName = 'item-current';

currentText = '今天';

} else {

currentText = i + 1;

// 判断选择样式与历史样式是否相等,相等激活

if (select_year == history_year && select_month == history_month && history_day == (i + 1)) {

currentClassName = 'item-active';

} else {

currentClassName = '';

}

}

// 添加tag样式

if (tags.length > 0) {

for (let j = 0; j < tags.length; j++) {

if ((i + 1) === tags[j]) {

currentClassName += 'item-tag';

break;

}

}

}

let current_link = (

{currentText}

);

current_days.push(current_link);

}

for (let i = 0; i < n_day; i++) {

let next_link = (

{i + 1}

);

next_days.push(next_link);

}

total_days = previous_days.concat(current_days, next_days);

let ul_list = [];

if (total_days.length > 0) {

for (let i = 0; i < row_number; i++) {

let li_list = [],

start_index = i * col_number,

end_index = (i + 1) * col_number;

for (let j = start_index; j < end_index; j++) {

li_list.push(total_days[j]);

}

ul_list.push(li_list);

}

}

return (

{select_year} 年 {select_month + 1} 月

{

ul_list.map((u, index) => {

return (

  • {u}

);

})

}

);

}

});

export default Calendar;

调用方式

import React from 'react';

import ReactDOM from 'react-dom';

import Calendar from './Calendar';

const App = React.createClass({

/**

* 初始状态

* @returns {{tags: number[]}}

*/

getInitialState() {

return {

tags : [5, 21]

}

},

/**

* 选择日期

* @param year

* @param month

* @param day

*/

selectDate(year, month, day) {

console.log("选择时间为:" + year + '年' + month + '月' + day + '日' );

},

/**

* 上一个月

* @param year

* @param month

*/

previousMonth(year, month) {

console.log("当前日期为:" + year + '年' + month + '月');

this.setState({tags : [7, 11]});

},

/**

* 下一个月

* @param year

* @param month

*/

nextMonth(year, month) {

console.log("当前日期为:" + year + '年' + month + '月');

this.setState({tags : [8, 23]});

},

/**

* 组件渲染

* @returns {XML}

*/

render() {

return (

onSelectDate={this.selectDate}

onPreviousMonth={this.previousMonth}

onNextMonth={this.nextMonth}

year="2016"

month="8"

day="7"

tags={this.state.tags} />

);

}

});

export default App;

react月份选择控件_看我的案例:用react写一个日历控件!相关推荐

  1. 让一个图片填满一个控件_如何在Android中实现一个全景图控件(二)

    一.背景 在 如何在Android中实现一个全景图控件(一)中,介绍了项目的一些基本情况(有 demo 演示),如果项目对你有帮助,希望文章赏个赞,项目 star 一下. 项目地址:https://g ...

  2. 用java程序写日历_用Java和C#写一个日历

    Java代码 package com.company; import java.time.DayOfWeek; import java.time.LocalDate; public class Mai ...

  3. 带你开发一个日历控件

    首发我的博客 - https://blog.cdswyda.com/post/2017121010 日历控件多的不胜枚举,为什么我们还要再造一个轮子呢? 因为大多数日历控件都是用于选择日期的,有种需求 ...

  4. vb.net 图形控件_玩转图形:VB.net GlassLabel控件

    vb.net 图形控件 A while ago, I was working on a Windows Forms application and I needed a special label c ...

  5. 自定义日历控android,Android 一个日历控件的实现小记

    先看几张动态的效果图吧! 这里主要记录一下在编写日历控件过程中一些主要的点: 一.主要功能 1.支持农历.节气.常用节假日 2.日期范围设置,默认支持的最大日期范围[1900.1~2049.12] 3 ...

  6. 梅花雨做的一个日历控件

    这是梅花雨做的一个日历 Javascript 页面脚本控件,适用于微软的 IE (5.0以上)浏览器 主调用函数是 setday(this,[object])和setday(this),[object ...

  7. react 动态添加组件属性_这么高质量React面试题(含答案),看到就是赚到了!...

    前言 本文篇幅较长,全是干货,建议亲们可以先收藏慢慢看哦 写文不易,欢迎大家一起交流,喜欢文章记得关注我点个赞哟,感谢支持! Q1 :什么是虚拟DOM? 难度::star: 虚拟DOM(VDOM)它是 ...

  8. python时间控件readonly属性_Selenium2+python自动化----js处理日历控件(修改readonly属性)...

    前言 日历控件是web网站上经常会遇到的一个场景,有些输入框是可以直接输入日期的,有些不能,以我们经常抢票的12306网站为例,详细讲解如何解决日历控件为readonly属性的问题. 基本思路:先用j ...

  9. 初步了解如何自己写一个网格控件

    网上下的一个源码,VC6打开如下: 一个MFC工程,控件的源码包含在demo工程里面:构建时是全部一起构建: 先看一下版权: // This code may be used in compiled ...

最新文章

  1. smarty实例教程
  2. 【mycat】简介及安装
  3. jquery ajax示例
  4. Day71 分页,cookie and Session
  5. _Ansible批量管理与维护
  6. 详解 nginx 配置文件及构建 web 虚拟主机
  7. ARM CORTEX M0 程序镜像和启动逻辑
  8. MapReduce 工作原理
  9. HTML、CSS、JS对unicode编码字符的规则
  10. 学编程不如学自动化?
  11. python编程软件哪个好-来 看看谁最适合学Python编程
  12. Makefile .PHONY用法
  13. PyTorch中查看GPU使用情况以及一些重要函数
  14. java bean规范 is_深入了解JavaBean规范中的属性名和setter/getter方法
  15. NOIP2017奶酪
  16. dplayer安装php_Dplayer播放器集成p2p加速源码分享
  17. android金山清理扫描文件动画,[Android开发实战]金山清理大师(猎豹清理大师)一键加速快捷方式动画实现...
  18. xposed新版52下载_kyqp游戏合集-kyqp游戏下载推荐
  19. 《系统架构设计》-01-架构和架构师概述
  20. AcWing1017.怪盗基德的滑翔翼

热门文章

  1. 数字信号 fft c源码_如何制作一个简单的人体动态识别微信小程序(附源码)
  2. python实现目标检测_由浅入深:教你如何构建一个行人目标检测模型(Python)
  3. 【连载】如何掌握openGauss数据库核心技术?秘诀五:拿捏数据库安全(1)
  4. 一次执行truncate触发ORA-02266解决过程
  5. 三问三答,解传统企业敏捷转型担忧
  6. 手把手带你玩转LiteOS Ping组件
  7. 数据膨胀了?你的数仓又没有空间了?
  8. 漫谈SCA(软件成分分析)测试技术:原理、工具与准确性
  9. 【Angular专题】 (3)装饰器decorator,一块语法糖
  10. c语言sqlserver进行odbc编程,在VS下用C语言连接SQLServer2008