在 Backbone 个集合中搜索,使用 React 更新 UI
Search in Backbone Collections, Updating UI with React
我正在花时间做一些可能很简单的事情:
我想实现一个搜索栏,理想情况下是按您的类型更新项目列表。我的小应用程序使用 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 方法首先将 backbone 集合转换为 "state" 但没有成功,我的想法是通过集合的副本进行代理,然后可以保存搜索结果。为了清楚起见,我没有在这里展示我的尝试(编辑:是的,我是),有人可以指导我采用正确的方法吗?提前致谢。
有很多方法可以做到这一点,但最简单的(在我看来)是将搜索条件存储在 List
组件的状态中,并使用它来过滤 collection 中的项目得到显示。您可以使用 Backbone collection 的内置 filter
方法来执行此操作。
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
搜索条件可以很容易地作为道具从 parent 组件传递下来,因此搜索输入不必存在于您的 List
组件中。
最终我也找到了一个不同的解决方案(如下),但它涉及将整个集合复制到状态中,这可能不是一个好主意...
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>
)
}
});
我正在花时间做一些可能很简单的事情: 我想实现一个搜索栏,理想情况下是按您的类型更新项目列表。我的小应用程序使用 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 方法首先将 backbone 集合转换为 "state" 但没有成功,我的想法是通过集合的副本进行代理,然后可以保存搜索结果。为了清楚起见,我没有在这里展示我的尝试(编辑:是的,我是),有人可以指导我采用正确的方法吗?提前致谢。
有很多方法可以做到这一点,但最简单的(在我看来)是将搜索条件存储在 List
组件的状态中,并使用它来过滤 collection 中的项目得到显示。您可以使用 Backbone collection 的内置 filter
方法来执行此操作。
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
搜索条件可以很容易地作为道具从 parent 组件传递下来,因此搜索输入不必存在于您的 List
组件中。
最终我也找到了一个不同的解决方案(如下),但它涉及将整个集合复制到状态中,这可能不是一个好主意...
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>
)
}
});