首页 文章

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

提问于
浏览
0

我正在关注反应网站上的一些教程,并尝试了一些示例代码 . 这是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 回答

  • 0

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

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

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

    例如,考虑功能:

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

    调用 foo 时,将使用以下两个条目创建新环境:

    <foo environment>
    bar: 21
    baz: 42
    

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


    In your code

    每次调用 renderSquare 时,都会创建一个带有条目 i 的新环境 .


    Closures 是可以解析本身未定义的变量的函数 . 请考虑以下示例:

    function add(x) {
      return function innerAdd(y) {
        return x + y;
      }
    }
    
    var add5 = add(5);
    add5(2); // 7
    

    这里, innerAdd 引用 x ,但 x 本身没有定义,而是在 add 中定义了"further up" .

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

    <add environment>
    x: 5
    

    innerAdd 有对该环境的引用!因此,当执行 add5 / innerAdd 时,它可以在该环境中查找 x . 您可以考虑链接在一起的环境:

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

    首先我们看看是否在 <innerAdd environment> 中定义了 x . 既然不是,我们看看它的父母等 .


    In your code

    使用 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?

  • 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)
    
  • 0

    它们存储在状态中,onclick也是一个已经具有索引的函数:

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

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

    此外,练习的目的是向您展示如何管理状态更改以及如何存储它,这在代码中完成,而不是一些自动反应的事情 . 每当动作完成时,整个状态(包括该索引)都存储在历史记录中 .

相关问题