实现穿越功能

记录历史步骤的列表里头,每一个步骤都有了一个唯一的ID,即这一步走的时候(he number of the move when it happened)。在Game组件的render方法里,这么添加key:<li key={move}>,刚才的警告就会消失。

code

const moves = history.map((step, move) => {
      const desc = move ?
        'Move #' + move :
        'Game start';
      return (
        <li key={move}>
          <a href="#" onClick={() => this.jumpTo(move)}>{desc}</a>
        </li>
      );
    });

查看最新的代码

点击里面的步骤,会报错。因为jumpTo方法还没定义。我们在Game组件的state里面新添加一条,用来指示当前的我们正在查看的步骤。

首先,在Game组件的constructor中,添加初始状态:stepNumber: 0

code

class Game extends React.Component {
  constructor() {
    super();
    this.state = {
      history: [{
        squares: Array(9).fill(null),
      }],
      stepNumber: 0,
      xIsNext: true,
    };
  }

下一步,在Game组件中,定义jumpTo方法,用以更新那条状态。xIsNext同样需要更新,如果一步棋的序号数是偶数,我们就把xIsNext的值设为true。

向Game的类增加jumpTo方法:

code

  handleClick(i) {
    // 本方法不做改动
  }

  jumpTo(step) {
    this.setState({
      stepNumber: step,
      xIsNext: (step % 2) ? false : true,
    });
  }

  render() {
    // 本方法不做改动
  }

为了实现在新走一步棋时,stepNumber可以更新的功能,我们在Game组件handleClick中的状态更新语句里添加stepNumber: history.length

code

  handleClick(i) {
    const history = this.state.history.slice(0, this.state.stepNumber + 1);
    const current = history[history.length - 1];
    const squares = current.squares.slice();
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      history: history.concat([{
        squares: squares
      }]),
      stepNumber: history.length,
      xIsNext: !this.state.xIsNext,
    });
  }

现在,你就可以修改Game组件的render函数,以实现从历史记录中读取步骤了。

code

render() {
    const history = this.state.history;
    const current = history[this.state.stepNumber];
    const winner = calculateWinner(current.squares);

    // the rest has not changed

查看最新的代码

现在你再点击列表里的步骤,棋盘应该就能立即更新,穿越回当时的那一步了。

你可能还想要更新handleClick,以便在读取当前board状态的时候,获取stepNumber。这样就能在穿越回去后,又点击棋盘时,创建新的步骤记录。(提示:最简单的办法,就是在handleClick的一开始,用.slice()把历史记录额外的元素切下来。)

results matching ""

    No results matching ""