传递的参数保存在渲染的React组件中的哪里

时间:2018-11-05 20:46:52

标签: javascript reactjs ecmascript-6

我正在React网站上关注一些教程,并尝试了一些示例代码。这是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方法。 / p>

这是 renderSquare 方法

renderSquare(i) {
        console.log(<Square/>);
        return (
            <Square
                value={this.props.squares[i]}
                onClick={() => this.props.onClick(i)}
            />
        );
    }

,此方法调用功能组件平方

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 (不在代码笔代码中),当我单击一个按钮(井字游戏,所以9个按钮)时,它将显示传递的参数( 0,1,2 ... 8)。

所以我的问题是这些数字存储在那些渲染的反应组件中的什么位置?我尝试使用控制台记录Square组件,但找不到该参数。 (这与道具或状态无关)

3 个答案:

答案 0 :(得分:0)

handleClick方法中,注销history,您会看到数据处于保存状态,在本例中为this.state.history。试试这个:

handleClick(i) {
    const history = this.state.history.slice(0, this.state.stepNumber + 1);
    const current = history[history.length - 1];
    console.log('history:', history)

答案 1 :(得分:0)

  

所以我的问题是这些数字存储在那些渲染的反应组件中的什么位置?

这与React无关。这就是函数在JavaScript中的工作方式。

每当调用一个函数时,就会创建一个新环境。环境是一个内部数据结构,用于保持状态(不要与React组件状态相混淆!)。参数和变量的值存储在该环境中。

例如考虑以下功能:

function foo(bar) {
  var baz = 42;
}

foo(21);

调用foo时,将创建一个具有两个条目的新环境:

<foo environment>
bar: 21
baz: 42

注意:函数调用是隔离的。每次调用函数时,都会为此调用创建一个新的环境。


在您的代码中

每次调用renderSquare时,都会使用条目i创建一个新环境。


关闭是可以解析本身未定义的变量的函数。考虑以下示例:

function add(x) {
  return function innerAdd(y) {
    return x + y;
  }
}

var add5 = add(5);
add5(2); // 7

在这里,innerAdd引用了x,但是x本身没有定义,它是 而是在add中定义为“进一步”。

执行add时,将创建一个新环境

<add environment>
x: 5

innerAdd 对此环境有参考!因此,执行add5 / innerAdd时,它可以在该环境中查找x。您可以考虑将环境链接在一起:

<innerAdd environment>
y: 2
parentEnvironment:
  <add environment>
  x: 5

首先,我们查看x中是否定义了<innerAdd environment>。既然不是,我们来看它的父级,等等。


在您的代码中

与在renderSquare中创建的事件处理程序完全相同。事件处理程序是在i=0(和/或i=1i=2等)环境中创建的函数。


这是一个不使用React的简化示例:

function createButton(i) {
  const button = document.createElement('button');
  button.textContent = 'Click me';
  button.onclick = () => console.log(i);
  document.body.appendChild(button);
}

createButton(0);
createButton(1);
createButton(2);

Chrome可让您检查与功能关联的环境。例如:

enter image description here

这些显示事件处理程序是在createButton内部创建的,其中i的值为0

另请参阅How do JavaScript closures work?

答案 2 :(得分:0)

它们以状态存储,onclick是已经具有索引的函数:

() => this.props.onClick(i)// line 16 in your code

i是您提供的索引,它会作为该函数的一部分保留在该函数中。函数是上下文感知的,因此当您在一个上下文中创建一个函数(闭包)时,它会继承创建该函数的上下文。因此,即使该函数在闭包之外定义,我也将永久存在于该函数中。

练习的重点还在于向您展示如何管理状态更改以及如何存储状态更改,这是在代码中完成的,而不是某些自动的反应。每当执行操作时,整个状态(包括该索引)都会存储到历史记录中。