为什么我们在ReactJs中省略回调将导致无法正常工作?

时间:2018-05-23 20:16:19

标签: javascript reactjs

    <button onClick = { () => this.restart()}>Restart</button>

在其中一个ReactJs教程中,该页面显示了一个游戏,它就像上面一样定义了重启按钮。 如果我用以下内容替换它,我不确定为什么它不起作用。

<button onClick = {this.restart()}>Restart</button>

我觉得上面和下面的内容不同之处仅在于上面是回调的方式,所以调用时间只会有一点差异,但似乎还有更多。

有人可以告诉我为什么会这样吗?

整个代码在下面。

&#13;
&#13;
class Game extends React.Component {

  constructor(props) {
    super(props)

    var cells = [];
    for (let i = 0; i < 6; i++) {
      cells.push(new Array(7).fill(0));
    }

    this.state = {
      player: false,
      cells: cells,
      winner: 0
    }
    this.handleClick = this.handleClick.bind(this)
  }
  checkDiagonal(row, col) {
    //find right and left tops
    var c = this.state.cells;
    var val = this.state.player ? 2 : 1;
    var rR = row;
    var cR = col;
    while (rR < 5 && cR < 6) {
      rR++;
      cR++;
    }

    while (rR >= 3 && cR >= 3) {
      if (c[rR][cR] == val && c[rR - 1][cR - 1] == val && c[rR - 2][cR - 2] == val && c[rR - 3][cR - 3] == val) {
        return 1
      }
      rR--
      cR--
    }

    var rL = row;
    var cL = col;

    while (rL < 5 && cL > 0) {
      rL++
      cL--
    }

    while (rL >= 3 && cL <= 3) {
      if (c[rL][cL] == val && c[rL - 1][cL + 1] == val && c[rL - 2][cL + 2] == val && c[rL - 3][cL + 3] == val) {
        return 1
      }
      rL--
      cL++
    }
    return 0
  }
  checkHorizontal(row, col) {
    var c = this.state.cells;
    var i = 6;
    var val = this.state.player ? 2 : 1;

    while (i >= 3) {
      if (c[row][i] == val && c[row][i - 1] == val && c[row][i - 2] == val && c[row][i - 3] == val) {
        return 1
      }
      i--
    }
    return 0
  }
  checkVertical(row, col) {
    var c = this.state.cells;
    var i = row;
    var val = this.state.player ? 2 : 1;

    if (i >= 3) {
      if (c[i][col] == val && c[i - 1][col] == val && c[i - 2][col] == val && c[i - 3][col] == val) {
        return 1
      }
    }
    return 0

  }
  checkVictory(row, col) {
    return this.checkVertical(row, col) || this.checkHorizontal(row, col) || this.checkDiagonal(row, col)


  }

  findAvailableRow(col) {


    for (var i = 0; i < 6; i++) {
      console.log(i, col)
      if (this.state.cells[i][col] == 0) {
        return i;
      }
    }
    return -1;
  }
  handleClick(row, col) {
    if (this.state.winner)
      return
    console.log("row: " + row + " | col: " + col)
    //console.log(this.state.cells)
    var temp = [];
    for (let i = 0; i < 6; i++) {
      temp.push(this.state.cells[i].slice())
    }
    var newRow = this.findAvailableRow(col)
    temp[newRow][col] = this.state.player ? 1 : 2
    this.setState({
      cells: temp,
      player: !this.state.player
    }, () => {


      if (this.checkVictory(newRow, col) > 0) {
        console.log("win")
        this.setState({
          winner: this.state.player ? 2 : 1
        })
      }


    })
  }
  restart() {
    var cells = [];
    for (let i = 0; i < 6; i++) {
      cells.push(new Array(7).fill(0));
    }
    this.setState({
      player: false,
      cells: cells,
      winner: 0
    })
  }
  render() {
    return ( <
      div >
      <
      h1 > {
        this.state.winner > 0 ? this.state.winner == 1 ? "Black Wins" : "Red Wins" : this.state.player ? "Blacks Turn" : "Reds Turn"
      } < /h1> <
      Board cells = {
        this.state.cells
      }
      handleClick = {
        this.handleClick
      }
      /> <
      button onClick = {
        () => this.restart()
      } > Restart < /button> <
      /div>
    )
  }
}

function Board(props) {
  var rows = []
  for (let i = 5; i >= 0; i--) {

    rows.push( < Row key = {
        i
      }
      row = {
        i
      }
      cells = {
        props.cells[i]
      }
      handleClick = {
        props.handleClick
      }
      />)
    }
    return ( <
      div > {
        rows
      } <
      /div>
    )
  }

  function Row(props) {
    var style = {
      display: "flex"
    }
    var cells = []
    for (let i = 0; i < 7; i++) {
      cells.push( < Cell key = {
          i
        }
        cell = {
          props.cells[i]
        }
        row = {
          props.row
        }
        col = {
          i
        }
        handleClick = {
          props.handleClick
        }
        />)
      }
      return ( <
        div style = {
          style
        } > {
          cells
        } <
        /div>
      )
    }

    function Cell(props) {

      var style = {
        height: 50,
        width: 50,
        border: "1px solid black",
        backgroundColor: "yellow"
      }

      return ( <
        div style = {
          style
        }
        onClick = {
          () => props.handleClick(props.row, props.col)
        } >
        <
        Circle cell = {
          props.cell
        }
        /> <
        /div>
      )
    }

    function Circle(props) {
      var color = "white"
      if (props.cell == 1) {
        color = "black"
      } else if (props.cell == 2) {
        color = "red"
      }

      var style = {
        backgroundColor: color,
        border: "1px solid black",
        borderRadius: "100%",
        paddingTop: "98%"
      }
      return ( <
        div style = {
          style
        } > < /div>
      )
    }

    ReactDOM.render( <
      Game / > ,
      document.getElementById('root')
    );
&#13;
<div id="root"></div>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:2)

看起来您正面临封装问题。

onClick侦听器将函数作为参数,因此当您单击调用该函数的按钮时。所以当你写:

<button onClick = {() => this.restart()}>Restart</button>

您正在为该按钮提供一个功能,该功能在被呼叫时会调用您的功能this.restart()

当你这样写:

<button onClick = {this.restart()}>Restart</button>

您正在为该按钮指定this.restart()的返回值。如果该函数没有返回任何内容,则此值将为undefined

所以,让我们说你的重启功能只记录一些东西:

restart() {
  console.log("something");
}

在第一种情况下,每次单击按钮时都会执行此功能,您可以看到日志。在第二种情况下,在渲染组件时会调用该函数。因此,当页面呈现时,您只会看到该日志一次,如果单击该按钮,则不会发生任何事情。

为了达到你想要做的,你应该这样写:

<button onClick = {this.restart}>Restart</button>

因为现在你没有调用该函数,所以你只是将它传递给你onClick监听器,只有在点击按钮时才会调用它。