【问题标题】:Search in Backbone Collections, Updating UI with React在 Backbone 集合中搜索,使用 React 更新 UI
【发布时间】:2015-04-16 02:48:26
【问题描述】:

我把时间花在了一些可能很简单的事情上: 我想实现一个搜索栏,理想情况下在你输入时更新项目列表。我的小应用使用 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 方法首先将骨干集合转换为“状态”,但没有成功,我的想法是通过集合的副本进行代理,然后可以保存搜索结果。为了清楚起见,我没有在这里展示我的尝试(编辑:是的,我是),有人可以指导我采用正确的方法吗?提前致谢。

【问题讨论】:

  • 您能否展示您在getInitialState? 中实现搜索的尝试?我的第一个想法是将search 存储在状态(或者如果它是由父母传入的道具)并过滤基于您的渲染方法中的集合。
  • 我同意@NickTomlin 的观点——如果你展示一些代码可能会有所帮助。例如,每当searchText 属性(如props.searchText)发生变化时,render 函数就可以执行实时过滤器。
  • 感谢@NickTomlin 和@WiredPrairie 的见解,这是我对getInitialState 方法的看法,项目数组应该使用搜索文本getInitialState: function () { initialState = this.getCollection().map(function(model) { return { id: model.cid, name: model.get('name'), description: model.get('description'), } }); return { init: initialState, items : [] } } 进行过滤,但这不是真的感觉不错,我觉得我应该能够在不通过 react 的状态概念的情况下进行搜索,而只使用集合
  • @senseye 为了可读性和清晰度,我会将您评论中的代码移到问题中。同样,我建议不要创建单独的集合。该视图只是集合的“显示”,您可以将 map 替换为 filter,并且只包含与您的搜索条件匹配的项目。
  • @NickTomlin,我更新了代码以包含整个反应元素,searchFilter 方法没有实现,因为我花了一些时间让其余部分合理地工作......据我所知,您是说将集合复制到状态以存储搜索是正确的方法?

标签: javascript search backbone.js reactjs


【解决方案1】:

有很多方法可以做到这一点,但最简单的(在我看来)是将您的搜索条件存储在List 组件的状态中,并使用它来过滤您的集合中的哪些项目会被显示。您可以使用 Backbone 集合的内置 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

搜索条件可以很容易地从父组件作为道具传递下来,因此搜索输入不必存在于您的 List 组件中。

【讨论】:

  • 谢谢!我刚刚发现了一些东西(我会在下面发布),但我更喜欢你的解决方案!确实过滤收藏是我错过的事情。
  • 谢谢,帮助我更好地理解 React :)
【解决方案2】:

最终我也找到了一个不同的解决方案(如下),但它涉及将整个集合复制到状态中,这可能不是一个好主意......

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>
        )
    }
}); 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-10
    • 2011-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多