实现穿越功能
记录历史步骤的列表里头,每一个步骤都有了一个唯一的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()
把历史记录额外的元素切下来。)