我是第一次玩 React,我想我真的很喜欢它。到目前为止,我已经实现了(大部分)棋盘游戏 Go 和它,但我遇到了一些奇怪的事情,我不知道如何以惯用的 React 方式处理。 基本上,我有一个模型 - 棋盘游戏 - 作为自己的类棋盘实现。它只公开它的构造函数,方法play(i,j)
和pass
。 它处理所有游戏逻辑并适当地更新自己的内部状态。 它不引用与视图/组件相关的任何内容。 我有一个名为BoardView的React组件,它维护对Board
实例的引用。 我还有一个名为AlertView
的组件,它在适当的时候显示有关游戏状态(非法移动等)的消息。
现在一切正常,我喜欢Board
类与其观点之间的关注点分离。 但是,我让我的Board
类传达其对视图的更改的方式是不寻常的,而且我觉得它与其他 React 代码不一致。 基本上,我滥用jQuery的事件系统来允许我触发任意事件,如["update", "atari", "suicide"]
。 在此方案中,组件具有调用Board.play
的 onClick 侦听器,这会在 Board 实例上触发 0 到许多事件。 组件侦听"update"
事件,并调用this.setState
,这将迫使它重新render()
,将视图置于正确描述游戏的状态。AlertView
侦听同一板实例上的"atari"
和"suicide"
事件,并类似地调用this.setState
,这会触发另一个render()
。
我应该删除jQuery事件吗?如果是这样,最好的方法是什么?
所有代码都在这里可用,你可以在这里玩这个应用程序。
编辑: 为了后人着想,这个问题是在提交 3f600c 时提出的。
我不确定这是否是惯用的 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);
},
})
Tungd 的评论为我指明了正确的方向,但我决定回答我自己的问题以获得更完整的答案。
我最终删除了在模型上触发的所有自定义事件。我发现 React 文档中的以下片段特别有用:
一种常见的模式是创建几个只渲染数据的无状态组件,并在层次结构中在其上方有一个有状态组件,该组件通过 props 将其状态传递给其子组件。有状态组件封装所有交互逻辑,而无状态组件负责以声明性方式呈现数据。
我没有在模型上触发"atari"和"suicide"等事件,我只是在模型上设置布尔属性in_atari
并attempted_suicide
。 现在,我的应用程序中只有一个"父"组件具有状态。 它通过声明性道具渲染所有子组件。AlertView
就是这样一个子组件,其render
方法现在检查新的布尔标志以呈现适当的文本。 主父组件将处理程序传递给其子组件,该子组件更新组件状态(并随后强制重新render
)。
在相关的提交中,我将父组件命名为 ContainerView。