听取模型变化的惯用方法

时间:2013-12-31 01:24:04

标签: javascript reactjs

我第一次玩React,我想我真的很喜欢它。我已经用它实现了(大部分)棋盘游戏Go到目前为止,但是我遇到了一些奇怪的东西,我不知道如何以惯用的React方式接近。基本上,我有一个模型 - 棋盘游戏 - 实现为自己的类Board。它只公开它的构造函数,以及方法play(i,j)pass。它处理所有游戏逻辑并适当更新其自身的内部状态。它没有引用与视图/组件相关的任何内容。我有一个名为BoardView的React组件,它维护对Board实例的引用。我还有一个名为AlertView的组件,它会在适当的时候显示有关游戏状态的信息(非法移动等)。

现在一切都运作良好,我喜欢Board类及其观点之间的关注点分离。但是,我让我的Board类将其更改传达给视图的方式很不寻常,我觉得它与其他React代码不一致。基本上,我滥用jQuery's event system允许我触发["update", "atari", "suicide"]之类的任意事件。在此方案中,Component具有一个调用Board.play的onClick侦听器,该侦听器触发Board实例上的0到多个事件。组件侦听"update"事件,并调用this.setState,这将强制重新render(),将视图置于正确描述游戏的状态。 AlertView会在同一个电路板实例上监听"atari""suicide"个事件,同样会调用this.setState,这会触发另一个render()

我应该删除jQuery事件吗?如果是这样,最好的方法是什么?

所有代码均可here,您可以使用应用here

编辑: 为了后人的缘故,在提交3f600c时提出了这个问题。

2 个答案:

答案 0 :(得分:2)

我不确定这是否是惯用的React,但是从React教程中,onSubmit处理程序作为props从父级传递给子级。

在您的情况下,这意味着将onPlay处理程序从BoardView传递到BoardIntersection,如下所示:

var BoardView = React.createClass({
  getInitialState: function() {
    return {"board": this.props.board}
  },
  playHandler: function(i, j) {
    this.props.board.play(i, j)
  },
  render: function() {
    ...
    intersections.push(BoardIntersection({
      color: this.state.board.board[i][j],
      row: i,
      col: j,
      onPlay: this.playHandler
    }));
    ...
  }
})

BoardIntersection会根据需要致电onPlay

var BoardIntersection = React.createClass({
  handleClick: function() {
    this.props.onPlay(this.props.row, this.props.col);
  },
})

答案 1 :(得分:2)

tungd的评论指出了我正确的方向,但我决定回答我自己的问题以获得更完整的答案。

我最终删除了在模型上触发的所有自定义事件。我发现以下snippet from the React docs特别有帮助:

  

一种常见的模式是创建几个只呈现数据的无状态组件,并在层次结构中有一个有状态的组件,通过props将其状态传递给子节点。有状态组件封装了所有交互逻辑,而无状态组件负责以声明方式呈现数据。

我没有在模型上触发像“atari”和“suicide”这样的事件,而只是在模型in_atariattempted_suicide上设置布尔属性。现在,我的应用程序中只有一个“父”组件具有状态。它通过声明性道具呈现所有子组件。 AlertView是一个这样的子组件,其render方法现在检查新的布尔标志以呈现适当的文本。主父组件将处理程序传递给其子组件,以更新组件状态(并随后强制重新render)。

在相关的commit中,我将父组件命名为ContainerView。