简单的日历组件

import React, { Component } from "react";
import * as _ from "lodash"; const l = console.log;
const weeks = ["日", "一", "二", "三", "四", "五", "六"];
class Test extends Component {
state = {};
componentWillMount() {
this.initState();
}
initState = ({ y, m } = {}) => {
let date = new Date();
let year = y || date.getFullYear(); // 本年
let month = m || date.getMonth() + 1; // 本月
l(`${year}年${month}月.`); let date2 = new Date(year, month, 0);
let days = date2.getDate(); // 本月有多少天
l(`本月有${days}天.`); date2.setDate(1);
let day = date2.getDay(); // 本月第一天是星期几
l(`本月第一天是星期${day}.`); let list = []; for (let i = 0; i < days + day; i++) {
if (i < day) {
list.push(0);
} else {
list.push(i - day + 1);
}
}
let hlist = _.chunk(list, 7); // 转化为二维数组
let len = hlist.length;
let to = 7 - hlist[len - 1].length; // 循环尾部补空格
for (let i = 0; i < to; i++) {
hlist[len - 1].push(0);
}
this.setState({
date,
year,
month,
days,
day,
hlist,
});
}; // 上月
handlePrevMonth = () => {
let prevMonth = this.state.month + -1;
let prevYear = this.state.year;
if (prevMonth < 1) {
prevMonth = 12;
prevYear -= 1;
}
this.initState({
y: prevYear,
m: prevMonth,
});
}; // 下月
handleNextMonth = () => {
let nextMonth = this.state.month + 1;
let nextYear = this.state.year;
if (nextMonth > 12) {
nextMonth = 1;
nextYear += 1;
}
this.initState({
y: nextYear,
m: nextMonth,
});
}; render() {
const { year, month } = this.state;
return (
<>
<h2>
{year}年,{month}月
</h2>
<div>
<button onClick={this.handlePrevMonth}>上月</button>
<button onClick={this.handleNextMonth}>下月</button>
</div>
<table>
<tbody>
<tr>
{weeks.map(el => (
<th key={el}>{el}</th>
))}
</tr>
{this.state.hlist.map((el, i) => {
return (
<tr key={i}>
{el.map((n, ii) => (
<td key={ii}>{n}</td>
))}
</tr>
);
})}
</tbody>
</table>
</>
);
}
} export default Test;

2

import React, { Component } from "react";
import * as _ from "lodash"; class DateItem {
/**
*
* @param dayNum 日数, 如果和 new Date().getDate() 相等则是今天
* @param isSignIn=false 是否签到
* @param isShowSignIn=false 是否显示是否签到,大于今日和这个月的日期应该都不显示
*/
constructor({ dayNum, isSignIn = false, isShowSignIn = false }) {
Object.assign(this, {
dayNum,
isSignIn,
isShowSignIn,
});
}
} const l = console.log;
const weeks = ["日", "一", "二", "三", "四", "五", "六"];
class Test extends Component {
state = {};
componentWillMount() {
this.initState();
}
initState = ({ y, m } = {}) => {
const date = new Date();
const year = y || date.getFullYear(); // 本年
const month = m || date.getMonth() + 1; // 本月 l(`${year}年${month}月.`); let date2 = new Date(year, month, 0);
let days = date2.getDate(); // 本月有多少天
l(`本月有${days}天.`); date2.setDate(1);
let day = date2.getDay(); // 本月第一天是星期几
l(`本月第一天是星期${day}.`); let list = [];
const nowadays = date.getDate(); // 本日
const thisMonth = date.getMonth() + 1; // 本月 let isShowSignIn = false;
const date2GtDate = date2 > date;
const isThisMonth = month === thisMonth; // 选择的日期的月份是否是本月 for (let i = 0; i < days + day; i++) {
const dayNum = i - day + 1;
if (date2GtDate) {
isShowSignIn = false;
} else {
if (isThisMonth && i >= day + nowadays) {
isShowSignIn = false;
} else {
isShowSignIn = true;
}
} if (i < day) {
list.push(new DateItem({ dayNum: 0, isShowSignIn }));
} else {
list.push(new DateItem({ dayNum, isShowSignIn }));
}
}
let hlist = this.getHlist(list, isShowSignIn);
this.setState({
date,
year,
month,
days,
day,
list,
hlist,
nowadays,
thisMonth,
});
}; // 把一维日期切成二维日期
getHlist = (list, isShowSignIn) => {
let hlist = _.chunk(list, 7); // 转化为二维数组
let len = hlist.length;
let to = 7 - hlist[len - 1].length; // 循环尾部补空格
for (let i = 0; i < to; i++) {
hlist[len - 1].push(new DateItem({ dayNum: 0, isShowSignIn }));
}
return hlist;
}; // 上月
handlePrevMonth = () => {
let prevMonth = this.state.month + -1;
let prevYear = this.state.year;
if (prevMonth < 1) {
prevMonth = 12;
prevYear -= 1;
}
this.initState({
y: prevYear,
m: prevMonth,
});
}; // 下月
handleNextMonth = () => {
let nextMonth = this.state.month + 1;
let nextYear = this.state.year;
if (nextMonth > 12) {
nextMonth = 1;
nextYear += 1;
}
this.initState({
y: nextYear,
m: nextMonth,
});
}; // 点击每个日期
handleDateItemClick = (dateItem, i, j) => () => {
const { year, month, date, nowadays } = this.state;
const { isShowSignIn, isSignIn, dayNum } = dateItem;
if (dayNum === 0) return;
const selectDate = new Date(`${year}-${month}-${dayNum}`);
if (nowadays === dayNum) {
l("签到");
} else if (selectDate < date) {
l("补签");
} if (!isShowSignIn || isSignIn)
// 不能签到的日期和已签到的日期直接返回
return; this.setState(state => {
const hlist = state.hlist.slice();
hlist[i][j].isSignIn = true;
return {
hlist,
};
});
};
render() {
const { year, month, nowadays, thisMonth } = this.state;
return (
<>
<h2>
{year}年,{month}月
</h2>
<div>
<button onClick={this.handlePrevMonth}>上月</button>
<button onClick={this.handleNextMonth}>下月</button>
<button
onClick={() => {
this.initState();
}}
>
今天
</button>
</div>
<table>
<tbody>
<tr>
{weeks.map(el => (
<th key={el}>{el}</th>
))}
</tr>
{this.state.hlist.map((el, i) => {
return (
<tr key={i}>
{el.map((dateItem, j) => {
const dayNum = dateItem.dayNum;
const isSignIn = dateItem.isSignIn;
const isShowSignIn = dateItem.isShowSignIn;
return (
<td
key={j}
style={{
color:
dayNum === nowadays && month === thisMonth && "red",
textAlign: "center",
padding: 8, border: "1px solid",
borderColor: dateItem.isSignIn
? "red"
: "transparent",
opacity: dayNum === 0 ? 0 : 1,
}}
onClick={this.handleDateItemClick(dateItem, i, j)}
>
<div>{dayNum}</div>
{!!isShowSignIn && (
<div
style={{
whiteSpace: "nowrap",
fontSize: "12px",
}}
>
{!!isSignIn ? `已签到` : `未签到`}
</div>
)}
</td>
);
})}
</tr>
);
})}
</tbody>
</table>
</>
);
}
} export default Test;

react 编写日历组件的更多相关文章

  1. React编写input组件传参共用onChange

    之前写页面上的input比较少,所以没有单提出来一个组件,今天研究了下input组件,但共用一个onChange的问题卡了一会儿,查了下发现几个比较好的方法,分享下: 方法一 Input组件 let ...

  2. 前端笔记之React(四)生命周期&Virtual DOM和Diff算法&日历组件开发

    一.React生命周期 一个组件从出生到消亡,在各个阶段React提供给我们调用的接口,就是生命周期. 生命周期这个东西,必须有项目,才知道他们干嘛的. 1.1 Mouting阶段[装载过程] 这个阶 ...

  3. react 编写组件 五

    看以下示例了解如何定义一个组件 // 定义一个组件LikeButton var LikeButton = React.createClass({ // 给state定义初始值 getInitialSt ...

  4. 日历组件 原生js

    自己基于原生js编写的日历组件 git地址: https://github.com/lihefen/calendar.git demo : https://lihefen.github.io/cale ...

  5. React jQuery公用组件开发模式及实现

    目前较为流行的react确实有很多优点,例如虚拟dom,单向数据流状态机的思想.还有可复用组件化的思想等等.加上搭配jsx语法和es6,适应之后开发确实快捷很多,值得大家去一试.其实组件化的思想一直在 ...

  6. react native 常用组件汇总

    react-native-uploader //文件上传https://github.com/aroth/react-native-uploader jpush-react-native //官方版本 ...

  7. 用 React 编写移动应用 React Native

    转载:用 React 编写移动应用 React Native ReactNative 可以基于目前大热的开源JavaScript库React.js来开发iOS和Android原生App.而且React ...

  8. 使用JavaScript和React编写原生移动应用

    使用JavaScript和React编写原生移动应用 React Native使你只使用JavaScript也能编写原生移动应用. 它在设计原理上和React一致,通过声明式的组件机制来搭建丰富多彩的 ...

  9. React高阶组件学习笔记

    高阶函数的基本概念: 函数可以作为参数被传递,函数可以作为函数值输出. 高阶组件基本概念: 高阶组件就说接受一个组件作为参数,并返回一个新组件的函数. 为什么需要高阶组件 多个组件都需要某个相同的功能 ...

随机推荐

  1. springmvc中select可以绑定enum中所有数据的方法

    public enum States { AK("AK"), AL("AL"), AR("AR"), AZ("AZ"), ...

  2. 招聘移动APP、接口、自动化、性能和安全方面的兼职测试讲师

    只要您在移动APP.接口.自动化.性能和安全方面有丰富的测试经验,我们都欢迎您能加入我们,成为我们的兼职测试讲师,我们可以提供给您一份优厚的薪资,同时能在行业发展.企业培训.授课经验.出版专业著作等方 ...

  3. unity加载ab后,场景shader不起效问题(物件表现黑色)

    需要把unity自带的shader,加入到默认列表

  4. x264阅读记录-3

      14. x264_macroblock_encode函数-1 这个函数主要根据已经选定的模式来对宏块残差进行编码. )如果是P_SKIP模式,那么调用x264_macroblock_encode_ ...

  5. 【UML】Java代码与UML模型相互转换方法

    最近重温了一下设计模式,看到大家的博客里面都是Java代码+UML视图,UML表达整体框架,然后再秀出具体的代码,点面结合.一目了然.所以也研究了一下Java代码与UML模型相互转换方法. 一.常用的 ...

  6. shell编程学习笔记(七):Shell中将指定内容输出到文件中

    我们这里把echo要打印的内容输出到文件中 以下蓝色字体部分为Linux命令,红色字体的内容为输出的内容: # cd /opt/scripts # vim script06.sh 开始编写script ...

  7. CentOS7配置MySQL5.7主备

    1:主库设置(1)修改配置文件vi /etc/my.cnf[mysqld]log-bin=master-binserver-id=1 (2)创建用户#mysql -u root -pmysql> ...

  8. js 动态生成html 触发事件传参字符转义

    通常,在使用 JS 动态生成 html 的过程中,会嵌入相应的样式.事件等属性元素,而这时经常会出现所谓的 “单.双引号不够用” 的情况,别急,这时可以利用 html 语言中的转义字符来解决.下面就来 ...

  9. 【Linux】CentOs的常用命令

    1.文件目录操作命令            ls:列出当前路径下的文件或者目录列表                -l 列出详细信息                -a 列出所有的文件信息,包括隐藏文 ...

  10. Atitit 烈火计划进展报告 r61

    Atitit 烈火计划进展报告 r61 1. 烈火计划主要包括几个东西 1 1.1. 2014.12 邮箱编码读取 1 1.2. 2017.1  垂直领域图片下载器  草料图片下载器 1 1.3. q ...