如何在 ReactJS 中创建动态表?
Posted
技术标签:
【中文标题】如何在 ReactJS 中创建动态表?【英文标题】:How to create a dynamic table in ReactJS? 【发布时间】: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()
。
【参考方案1】:
几个建议:
对所有元素使用 JSX 语法。例如,你可以这样做
let table = <table/>;
同样,您可以使用map()
而不是forEach()
创建<td>
元素:
let tds = days.map(day => <td>day</td>);
现在您需要将此日期列表拆分为每个 <tr>
的正确组。
将getMonth()
减少为一行并返回:
return this.months[month];
创建一个名为isLeapYear()
的函数以使该计算更具可读性。
【讨论】:
以上是关于如何在 ReactJS 中创建动态表?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 swift 中在动态 TableView 中创建动态 tableView?