如何在 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>

我使用过createElementappendChild,但每次我点击上一个/下一个按钮时,它都会在表格中添加新的行和单元格。

如何创建一个更新现有行/单元格而不是创建新行/单元格的表格?

【问题讨论】:

你有没有研究过类似react-datepicker 的东西可以为你解决这个难题? 不,我没有。由于我是编码新手,尤其是 ReactJS 新手,所以我想将这段代码作为练习,但我认为看看这个工作应用程序会很有帮助,因为它并不像我想象的那么容易...... 追加是不错的选择,但你必须先清空表,然后添加新行才能更新。 你应该把这个任务分成更小的部分。例如,制作一个Month 组件。最终目标是使用name 道具或类似的东西来指示它是几月,然后生成一个带有日期数字的网格,第一个从一周中正确的一天开始。然而,一次完成所有这些是很困难的。所以退后一步,用数字 1 到 30 制作一个网格,然后从星期日开始。一旦你得到这个工作,然后一次添加更多功能。 请注意,在 React 中,您可以使用 let table = &lt;table&gt;&lt;/table&gt; 而不是使用 createElement() 【参考方案1】:

几个建议:

    对所有元素使用 JSX 语法。例如,你可以这样做

    let table = <table/>;
    

    同样,您可以使用map() 而不是forEach() 创建&lt;td&gt; 元素:

    let tds = days.map(day => <td>day</td>);
    

    现在您需要将此日期列表拆分为每个 &lt;tr&gt; 的正确组。

    getMonth() 减少为一行并返回:

    return this.months[month];
    

    创建一个名为isLeapYear() 的函数以使该计算更具可读性。

【讨论】:

以上是关于如何在 ReactJS 中创建动态表?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Thymeleaf 中创建动态表..?

在As3中创建一个动态表

使用钩子在 Reactjs 中创建一个动态占位符

如何在 swift 中在动态 TableView 中创建动态 tableView?

在存储过程中创建动态表而在 PL/SQL 块表中创建时权限不足[重复]

如何在sql中创建动态where子句?