【发布时间】:2019-01-06 05:20:59
【问题描述】:
我正在尝试使用 ReactJS 编写日期选择器,但我不知道如何创建一个动态表,每次点击上一个或下一个按钮时显示实际月份的天数。
这是我的代码:
// Next step I need to add a matrix of weekdays (1..31) and check each month existing days including leap year days
class DatePicker extends React.Component {
constructor(props) {
super(props);
this.date = new Date();
this.months = [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
];
this.days = [
"sunday",
"monday",
"tuesday",
"wednesdey",
"thursday",
"friday",
"saturday"
]; // Should add keys for each item
this.listWeekDays = this.days.map(day => (
<li key={day}> {day.slice(0, 2)}</li>
)); // su mo tu we th fr sa
this.state = {
month: this.date.getMonth(),
year: this.date.getFullYear(),
monthDays: [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31
]
};
this.month = () => this.getMonth(this.state.month);
this.year = () => this.getYear(this.state.year);
// ***************** days of month
this.monthDays = [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31
];
/* ******************* EventHandling Binding ***************** */
this.getNext = this.getNext.bind(this);
this.getPrevious = this.getPrevious.bind(this);
/* *********************************************************** */
}
getPrevious() {
if (this.state.month >= 1) {
this.setState(prevState => ({ month: prevState.month - 1 }));
} else {
this.setState(prevState => ({ month: 11 }));
this.setState(prevState => ({ year: prevState.year - 1 }));
}
}
getNext() {
if (this.state.month < 11) {
this.setState(prevState => ({ month: prevState.month + 1 }));
} else {
this.setState(prevState => ({ month: 0 }));
this.setState(prevState => ({ year: prevState.year + 1 }));
}
}
getWeekDays() {
return <li>{this.listWeekDays}</li>;
}
getFirstDay() {
// console.log(typeof(this.month()));
// console.log(typeof(this.year()));
const year = this.year().toString();
const month = this.state.month;
const firstDay = new Date(year, month, "01");
return firstDay.getDay();
}
getMonth(month) {
switch (month) {
case 0:
return this.months[0];
case 1:
return this.months[1];
case 2:
return this.months[2];
case 3:
return this.months[3];
case 4:
return this.months[4];
case 5:
return this.months[5];
case 6:
return this.months[6];
case 7:
return this.months[7];
case 8:
return this.months[8];
case 9:
return this.months[9];
case 10:
return this.months[10];
case 11:
return this.months[11];
}
}
getYear(year) {
return year;
}
displayDays = (days, month, year, firstDay) => {
let tr = document.createElement("tr");
let td;
let table = document.createElement("table");
let body = document.getElementsByTagName("body")[0];
let i = 0;
let textNode;
const emptyTds = () => {
for (let j = 0; j < firstDay; j++) {
days.unshift("");
}
return days;
};
const checkMonthDays = () => {
if (month === 3 || month === 5 || month === 8 || month === 10) {
days = days.splice(0, 30);
} else if (month === 1) {
// Check if leap year or not
if (year % 4 === 0) {
if (year % 100 === 0) {
if (year % 400 === 0) {
days = days.splice(0, 29);
} else days = days.splice(0, 28);
} else days = days.splice(0, 29);
} else days = days.splice(0, 28);
}
return days;
};
const displayDaysTable = () => {
days.forEach(day => {
i++;
td = document.createElement("td");
textNode = document.createTextNode(day);
td.appendChild(textNode);
tr.appendChild(td);
if (i % 7 === 0) {
tr = document.createElement("tr");
}
table.appendChild(tr);
body.appendChild(table);
});
};
checkMonthDays();
emptyTds();
displayDaysTable();
};
render() {
return (
<div>
<div className="ympicker-container">
<div>
<input
type="button"
className="month-button"
value="<"
onClick={this.getPrevious}
/>
</div>
<div className="monthyear-container">
{this.month()} {this.year()}
</div>
<div>
<input
type="button"
className="month-button"
value=">"
onClick={this.getNext}
/>
</div>
</div>
<div className="week-days-container">
<ul className="days-ul"> {this.listWeekDays} </ul>
</div>
<div>
{this.getFirstDay()} //this is the first weekday of the month
</div>
<div>
{this.displayDays(
this.monthDays,
this.state.month,
this.state.year,
this.firstDay
)}
</div>
</div>
);
}
}
const DaysTable = () => {
return <div />;
};
ReactDOM.render(<DatePicker />, app);
.ympicker-container {
display: flex;
border: 1px solid black;
justify-content: space-between;
align-items: center;
background: #DCDCDC;
width: 250px;
font-size: 18px;
font-weight: 600;
padding: 0px 0;
font-family: arial, sans serif;
}
.month-button {
border: 0px solid blue;
font-size: 16px;
font-weight: 700;
color: blue;
height: 40px;
cursor: pointer;
outline: none;
padding: 0 15px;
}
.month-button:hover {
background: #191970;
color: white;
}
.week-days-container {
display: flex;
border: 1px solid black;
border-top: 0;
width: 250px;
height: 25px;
overflow:hidden;
}
.days-ul {
display: flex;
flex-direction: row;
align-items: center;
list-style: none;
font-size: 20px;
flex-grow:1;
padding: 0;
margin: 0;
}
li {
display:flex;
flex-grow: 1;
align-items: center; /* Center items */
flex-direction:column;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
我使用过createElement 和appendChild,但每次我点击上一个/下一个按钮时,它都会在表格中添加新的行和单元格。
如何创建一个更新现有行/单元格而不是创建新行/单元格的表格?
【问题讨论】:
-
你有没有研究过类似react-datepicker 的东西可以为你解决这个难题?
-
不,我没有。由于我是编码新手,尤其是 ReactJS 新手,所以我想将这段代码作为练习,但我认为看看这个工作应用程序会很有帮助,因为它并不像我想象的那么容易......
-
追加是不错的选择,但你必须先清空表,然后添加新行才能更新。
-
你应该把这个任务分成更小的部分。例如,制作一个
Month组件。最终目标是使用name道具或类似的东西来指示它是几月,然后生成一个带有日期数字的网格,第一个从一周中正确的一天开始。然而,一次完成所有这些是很困难的。所以退后一步,用数字 1 到 30 制作一个网格,然后从星期日开始。一旦你得到这个工作,然后一次添加更多功能。 -
请注意,在 React 中,您可以使用
let table = <table></table>而不是使用createElement()。
标签: javascript arrays reactjs html-table jsx