在过去的几周里,我一直在使用facebooks框架React.js和Backbone一起工作.当Backbone集合发生变化时,我仍然不能完全确定重新渲染React组件的最佳方法是什么已作为道具传入.
目前我所做的是在componenentWillMount
集合上设置change/add/remove
监听器并在触发时设置状态:
componentWillMount: function(){ var myCollection = this.props.myCollection; var updateState = function(){ this.setState({myCollection: myCollection.models}); } myCollections.on("add remove", updateState, this); updateState(); } render: function(){ var listItems = this.state.myCollection.map(function(item){ return
我已经看到了将模型克隆到状态的示例:
var updateState = function () { this.setState({ myCollection: _.clone(this.myCollection.models) }); };
我也看到过变体,其中props中的模型/集合直接用于渲染而不是使用状态,然后在集合/模型更改时调用forceUpdate,导致组件重新渲染
componentWillMount: function(){ var myCollection = this.props.myCollection; myCollections.on("add remove", this.forceUpdate, this); } render: function(){ var listItems = this.props.myCollection.map(function(item){ return
不同的方法有哪些好处和缺点?有没有办法做到这就是The React方式?
您可以使用基于此BackboneMixin的mixin来帮助自动绑定和取消绑定侦听器,而不是手动绑定事件侦听器:
https://github.com/facebook/react/blob/1be9a9e/examples/todomvc-backbone/js/app.js#L148-L171
然后你就写了
var List = React.createClass({ mixins: [BackboneMixin], getBackboneModels: function() { return [this.props.myCollection]; }, render: function(){ var listItems = this.props.myCollection.map(function(item){ return <li>{item.get("someAttr")}</li>; }); return <ul>{listItems}</ul>; } });
当集合中的任何更改时,组件将被重新呈现.您只需要将BackboneMixin放在顶级组件上 - 任何后代将同时自动重新呈现.
IMO,React仍然非常新,关于如何使用Backbone等数据和反应模型的规则很少.如果您有一个现有的应用程序,这也是一个优势 - 可以将反应集成到它的一些较小部分,而无需重新定义整个数据流.
我相信,因为React可以在任何时候调用渲染"智能" - 这只是重新渲染已经改变的部分 - 你真的不需要将数据作为状态传递.只需传递数据,在顶部组件上添加侦听器,并forceUpdate
在模型发生更改时调用它,它将很好地传播下来.
将骨干模型作为道具而不是状态传递似乎更"正确".
我学到很难的一件重要事情是在渲染骨干模型列表时使用model.cid
as键(而不是Math.random()
):
var listItems = this.props.myCollection.map(function(item){ return <li key={item.cid}>{item.get("someAttr")}</li>; });
因为否则React将无法识别要重新渲染的模型,因为所有模型都会在每个渲染上都有新的键.
我一直在玩这里提到的BackboneMixin和其他一些反应资源(目前有限的信息).我发现当我正在收听从服务器更新的集合时,就会在集合上触发多个n'add'事件并由BackboneMixin监听,因此调用force update n次,它调用渲染和从渲染n次调用的任何东西.
相反,我使用下划线/ lo-dash的节流方法来限制forceUpdate的调用次数.至少这限制了渲染方法被调用这么多.我知道react实际上并没有在那里进行任何DOM操作,它只是一个虚拟DOM,但仍然没有理由它应该被100次调用100次立即添加到Collection.
所以我的解决方案看起来像https://gist.github.com/ssorallen/7883081但是使用了像这样的componentDidMount方法:
componentDidMount: function() { //forceUpdate will be called at most once every second this._boundForceUpdate = _.throttle(this.forceUpdate.bind(this, null), 1000); this.getBackboneObject().on("all", this._boundForceUpdate, this); }