ReactJS以正确的方式绑定组件方法

ReactJS bind a component method the correct way

本文关键字:绑定 组件 方法 方式 ReactJS      更新时间:2023-09-26

在组件中使用方法时,我正在尝试使用.bind()。原因很简单:在一个循环中,我正在返回组件,并用一个调用方法的属性来扩展它们。但对于每个循环项,我都想用一些信息(比如键)来扩展this对象。

示例:

项目.jsx

Items = React.createClass({
  eventMethod() {
    console.log('this event was triggered by key:', this.key);
  },
  items() {
    let items = [];
    let properties = {};
    _.each(this.props.items, (itemData, key)=>{
      properties.eventMethodInItem = this.eventMethod.bind(_.extend(this, {
        key
      }));
      let {...props} = properties;
      let item = <Item {...props} key={key} />;
      items.push(item);
    });
    return items;
  },
  render() {
    return(<div>{this.items()}</div>);
  }
});

Item.jsx

Item = React.createClass(...);

在这种情况下(及其工作),当项目组件触发道具"eventMethodInItem"时,将调用我的方法"eventMethod",并且this.key具有正确的值!

那么,现在的问题是什么?它运行得很完美,对吧?

但是ReactJS不希望我这样做。这就是ReactJS作为控制台日志告诉我的。

警告:bind():您正在将组件方法绑定到组件。React以高性能的方式自动为您执行此操作,因此您可以安全地删除此调用。参见项目

也许你认为像我这样把孩子添加到组件中是一种"糟糕"的方式,但在我的特殊情况下,我需要用这种方式来做——所以我需要把新信息绑定到一个方法上。

我不会假装我理解你在这里想做什么,但也许我无论如何都可以帮你澄清。

React获取在每个组件上找到的所有顶级方法,并自动将它们绑定到组件的上下文。

这防止了其他方法覆盖this的上下文,因此,如果您试图重新绑定该方法,React会说"嘿,别担心。我已经得到了"——这就是您看到的警告。

假设真的想要这样做(每次通过重写eventMethodInItem属性来更改外部properties对象时)。

properties.eventMethodInItem = this.eventMethod.bind(_.extend(this, {
  key
}));

然后,我看不出eventMethod必须存在于组件上的任何原因,而不仅仅是在items函数的范围内。

items() {
  const eventMethod = function() {
    console.log('this event was triggered by key:', this.key);
  }
  // ...
  _.each(this.props.items, (itemData, key)=>{
    properties.eventMethodInItem = eventMethod.bind(_.extend(this, {
      key
    }));
    // ...
  });
},

这样,你就不必为了让你的程序发挥作用而与React斗争。

React在使用React.createClass时已经在自动绑定thishttp://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html#under-引擎盖自动绑定和事件委派

将绑定更改为

properties.eventMethodInItem = this.eventMethod.bind(null,key);

和你的eventMethod

eventMethod(key) {
    console.log('this event was triggered by key:', key);
}

我还建议使用_.map而不是_.each

items() {
  return _.map(this.props.items, (itemData, key) => {
    return <Item
          handleEventMethod={this.eventMethod.bind(null,key)}
          key={key} />;
  });
},

良好的模式https://www.newmediacampaigns.com/blog/refactoring-react-components-to-es6-classes

之前:

class ExampleComponent extends React.Component {
 constructor() {
  super();
  this. _handleClick = this. _handleClick.bind(this);
  this. _handleFoo = this. _handleFoo.bind(this);
 }
 // ...
}

之后:

class BaseComponent extends React.Component {
 _bind(...methods) {
  methods.forEach( (method) => this[method] = this[method].bind(this) );
 }
}
class ExampleComponent extends BaseComponent {
 constructor() {
  super();
  this._bind('_handleClick', '_handleFoo');
 }
 // ...
}

这个话题的另一个好技巧http://egorsmirnov.me/2015/08/16/react-and-es6-part3.html