我正在关注反应网站上的一些教程,并尝试了一些示例代码 . 这是codepen中该代码的链接
https://codepen.io/gaearon/pen/gWWZgR?editors=0010
以下是该问题的一些片段
<div className="board-row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
这将调用 renderSquare 方法传递一个数字作为参数,这将有助于根据 square (这是一个按钮)识别onClick方法 .
这是 renderSquare 方法
renderSquare(i) {
console.log(<Square/>);
return (
<Square
value={this.props.squares[i]}
onClick={() => this.props.onClick(i)}
/>
);
}
并且此方法调用功能组件 Square ,
function Square(props) {
return (
<button className="square" onClick={props.onClick}>
{props.value}
</button>
);
}
因此,当单击一个正方形时,它将调用 handleClick(i) 方法(更好地查看codepen链接,以便您了解整个代码)
handleClick(i) {
console.log(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,
});
}
因此,通过使用console.log(不在codepen代码中),当我单击一个按钮(tic-tac-toe游戏,所以9个按钮)时,它将显示传递的参数(0,1,2 ... 8) .
所以我的问题是这些数字存储在那些渲染的反应组件中?我试过控制台记录Square组件,但我找不到那个参数 . (这与道具或国家无关)
3 回答
这与React无关 . 这是函数在JavaScript中的工作方式 .
每当调用函数时,都会创建一个新环境 . 环境是保持状态的内部数据结构(不要与React组件状态混淆!) . 参数和变量的值存储在该环境中 .
例如,考虑功能:
调用
foo
时,将使用以下两个条目创建新环境:Note: 函数调用是隔离的 . 每次调用函数时,都会为此调用创建一个新环境 .
In your code
每次调用
renderSquare
时,都会创建一个带有条目i
的新环境 .Closures 是可以解析本身未定义的变量的函数 . 请考虑以下示例:
这里,
innerAdd
引用x
,但x
本身没有定义,而是在add
中定义了"further up" .执行
add
时,将创建一个新环境innerAdd
有对该环境的引用!因此,当执行add5
/innerAdd
时,它可以在该环境中查找x
. 您可以考虑链接在一起的环境:首先我们看看是否在
<innerAdd environment>
中定义了x
. 既然不是,我们看看它的父母等 .In your code
使用
renderSquare
中创建的事件处理程序完全相同 . 事件处理程序是在i=0
(和/或i=1
,i=2
等)的环境中创建的函数 .这是一个不使用React的简化示例:
Chrome可让您检查与功能相关的环境 . 例如:
这些显示事件处理程序是在
createButton
中创建的,其中i
的值为0
.另见How do JavaScript closures work?
在
handleClick
方法中,注销history
,您将看到数据以状态保存,在本例中为this.state.history
. 试试这个:它们存储在状态中,onclick也是一个已经具有索引的函数:
我是你给的索引,它作为该函数的一部分保留在该函数中 . 函数是上下文感知的,所以当你在一个上下文中创建一个函数(闭包)时,它会继承它所创建的上下文 . 因此,即使它是在闭包之外定义的,我将永久地存在于该函数中 .
此外,练习的目的是向您展示如何管理状态更改以及如何存储它,这在代码中完成,而不是一些自动反应的事情 . 每当动作完成时,整个状态(包括该索引)都存储在历史记录中 .