React JS - 处理子点击事件的好方法是什么?

时间:2015-06-29 21:29:42

标签: javascript reactjs

我有一个包含大约2k项目的列表。如果我对每个孩子使用onClick,我最终会得到2k听众,这就是我目前所拥有的。我想做一些事情,比如让父组件听取点击事件。但是,如果我这样做,我就没有引用我需要调用setState的子组件。还可以动态过滤子组件列表(使用this.refs可能不好?)。

我能想到的最好的方法是将子组件id的哈希映射到父组件中的子组件,并在单击时查找视图。

仅用于说明目的:

  var Parent = React.createClass({
      shouldComponentUpdate: function() { return false; },
      handler: function(e) {
         // look up from reference and set state   
      },
      componentWillUnmount: function() {
        // clean up reference   
      },
     render: function() {
       this.reference = {};
       var items = [];
       for(var i = 0; i < this.props.items.length; i++) {
         var child = React.createClass(Child, {id: this.props.items[i].id});
         items.push(child);
         reference[child.id] = child; 
       }
         return React.createClass('div', {onClick: this.handler}, items);
     }
  })

我想知道是否有React处理这个问题的方法。

3 个答案:

答案 0 :(得分:3)

我认为这个答案可能会有所帮助......如果您有2000个事件处理程序或只有一个事件处理程序并不重要。 React以同样的方式处理它。请记住,您在render方法中返回的HTML不会添加到DOM中,但它只是由React用于构建虚拟DOM表示。最后,React只有一个onClick。

React efficient way to bind event to many dom elements

如果你需要知道触发点击的元素,你只需要访问event.target并使用任何数据属性来识别被点击的元素。

答案 1 :(得分:1)

React的做法是使用Flux调度程序+商店。基本上,一旦商店执行了您希望它完成的任务,您就可以将每个项目绑定到从商店触发的事件。

所以流程将是:

  

项目被点击=&gt;调度Flux事件=&gt; Flux调度程序检测事件并使用从Item组件传递的数据执行适当的函数。

  var ItemStore = {
    doSomething: function(data){
      // do something with the data
    }
  }
  MicroEvent.mixin(ItemStore);

  var AppDispatcher = new Dispatcher();

  AppDispatcher.register(function(payload) {

    switch (payload.eventName) {
      case 'item-clicked':
        ItemStore.doSomething(payload.data.someData);
        ItemStore.trigger('did-something');
    }

    return true;

  })


  var Item = React.createClass({
      shouldComponentUpdate: function() { return false; },
      componentDidMount: function() {
        ItemStore.bind('did-something', this.submitHandled);
      },
      handler: function(e) {
        AppDispatcher.dispatch({
          eventName: 'item-clicked',
          data: {
            someData: 'sample data'
          }
        });
      },
      componentWillUnmount: function() {
        // clean up reference   
      },
      submitHandled: function() {
        // do something after the click
      },
     render: function() {
       // insert your item's html here. 
     }
  })

答案 2 :(得分:1)

@damianmr 的答案为基础,这里是an example

var Child = React.createClass({
  shouldComponentUpdate(nextProps){
    if (this.props.text !== nextProps.text) return true;
    if (this.props.active !== nextProps.active) return true;
    return false;
  },
  render(){
    var className = 'Child';
    if (this.props.active) className += ' Child-active';

    return (
      <div {...this.props} className={className}>
        {this.props.text}
      </div>
    );
  }
});
var Parent = React.createClass({
  getInitialState(){
    return {active: -1};
  },

  setActive(id){
    this.setState({active: id});
  },

  render(){
    return (
      <div>
        {this.props.items.map((item) => {
         return (
           <Child
             active={this.state.active === item.id}
             onClick={() => this.setActive(item.id)}
             text={'My id is ' + item.id}
             key={item.id}
           />
         );
        })}
      </div>
    );
  }
});