我花时间做一些可能很简单的事情: 我想实现一个搜索栏,理想情况下更新项目列表为你。我的小应用程序使用React和Backbone(用于模型和集合)。
显示列表并不太难,这一切都很完美(我正在使用的mixin基本上允许简单的集合检索):
var List = React.createClass ({
mixins: [Backbone.React.Component.mixin],
searchFilter: function () {
//some filtering code here, not sure how (filter method is only for arrays...)
}
}
getInitialState: function () {
initialState = this.getCollection().map(function(model) {
return {
id: model.cid,
name: model.get('name'),
description: model.get('description')
}
});
return {
init: initialState,
items : []
}
},
componentWillMount: function () {
this.setState({items: this.state.init})
},
render: function(){
var list = this.state.items.map(function(obj){
return (
<div key={obj.id}>
<h2>{obj.name}</h2>
<p>{obj.description}</p>
</div>
)
});
return (
<div className='list'>
{list}
</div>
)
}
});
现在我尝试使用getInitialState方法将主干集合转换为“状态”没有成功,我的想法是通过集合的副本代理,然后可以保存搜索结果。为了清楚起见,我没有在这里展示我的尝试(编辑:我是),有人能引导我采用正确的方法吗?提前谢谢。
答案 0 :(得分:1)
有很多方法可以实现这一目标,但最简单的(在我看来)是将搜索条件存储在List
组件的状态,并使用它来过滤显示集合中的哪些项目。您可以使用filter
方法内置的Backbone集合来执行此操作。
var List = React.createClass ({
mixins: [Backbone.React.Component.mixin],
getInitialState: function () {
return {
nameFilter: ''
};
},
updateSearch: function (event) {
this.setState({
nameFilter: event.target.value
});
},
filterItems: function (item) {
// if we have no filter, pass through
if (!this.state.nameFilter) return true;
return item.name.toLowerCase().indexOf(this.state.nameFilter) > -1;
},
render: function(){
var list = this.props.collection
.filter(this.filterItems.bind(this))
.map(function(obj){
return (
<div key={obj.id}>
<h2>{obj.name}</h2>
</div>
)
});
return (
<div className='list'>
{list}
<input onChange={this.updateSearch} type="text" value={this.state.nameFilter}/>
</div>
)
}
});
var collection = new Backbone.Collection([
{
name: 'Bob'
},
{
name: 'Bill'
},
{
name: 'James'
}
]);
React.render(<List collection={collection}/>, document.body);
<强> jsbin 强>
搜索条件可以很容易地从父组件传递下来作为道具,因此搜索输入不必存在于List
组件内。
答案 1 :(得分:0)
最终我还找到了一个不同的解决方案(下图),但它涉及将整个集合复制到状态,这可能不是一个好主意......
var List = React.createClass ({
mixins: [Backbone.React.Component.mixin],
searchFilter: function () {
var updatedlist = this.state.init;
var searchText = this.refs.searchbar.getDOMNode().value
updatedlist = updatedlist.filter(function (item) {
return item.name.toLowerCase().search(
searchText.toLowerCase()) !== -1
});
this.setState({items: updatedlist})
}
},
getInitialState: function () {
initialState = this.getCollection().map(function(model) {
return {
id: model.cid,
name: model.get('name'),
description: model.get('description')
}
});
return {
init: initialState,
items : []
}
},
componentWillMount: function () {
this.setState({items: this.state.init})
},
render: function(){
var list = this.state.items.map(function(obj){
return (
<div key={obj.id}>
<h2>{obj.name}</h2>
<p>{obj.description}</p>
</div>
)
});
return (
<div className='list'>
<input ref='searchbar' type="text" placeholder="Search" onChange={this.searchFilter}/>
{list}
</div>
)
}
});