【问题标题】:How to create a dynamic table in ReactJS?如何在 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()

标签: javascript arrays reactjs html-table jsx


【解决方案1】:

几个建议:

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

    let table = <table/>;
    
  2. 同样,您可以使用map() 而不是forEach() 创建&lt;td&gt; 元素:

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

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

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

    return this.months[month];
    
  4. 创建一个名为isLeapYear() 的函数以使该计算更具可读性。

【讨论】:

    猜你喜欢
    • 2016-04-09
    • 1970-01-01
    • 1970-01-01
    • 2016-11-26
    • 1970-01-01
    • 2017-07-12
    • 1970-01-01
    • 1970-01-01
    • 2018-03-14
    相关资源
    最近更新 更多