React.js中的OnClick事件绑定

Swa*_*osh 40 javascript reactjs

我想传递父divID,点击该div或任何相同的子元素div.但我无法实现它.请告诉我我在哪里弄错了.代码如下:

viewMore: function(i,j){
        console.log('You clicked: ', i  );
    },

render : function(){
  var attributeId = "groups_";
  attributeId+= index;
  return(
  //parent div
    <div className="groups" id={attributeId} onClick={this.viewMore}>
        <div className="floatLeft"> Group Name: <h3>My Name</h3></div>
            <span className="floatRight typeCd">POC</span>
        <div className="clearfix"> Key Attributes: 
            <ul>
                <li> POC 1</li>
            </ul>
        </div>
    </div>
    )
};
Run Code Online (Sandbox Code Playgroud)

Hen*_*son 50

viewMore = (i,j) => () => {
    console.log(i,j)
}
Run Code Online (Sandbox Code Playgroud)

要将参数传递给事件处理程序,我们需要使用currying.使用上述方法,在调用render时,不会一直创建新函数.

  • ^^只是`.bind(null,attributeId)` (7认同)
  • @George仍会在每个`render`调用上运行`bind`.浪费的.IMO的最佳方法是在构造函数中执行:`this.onclick = this.handleClick.bind(this);`然后,在`handleClick`中,从React事件中检索`attributeId`:`const {attributeId} = event.target`. (5认同)
  • 这是一个[CodePen](http://codepen.io/anon/pen/rrpwaw?editors=1011),说明了这种方法. (3认同)
  • Zen是正确的 - 如果在组件中使用构造函数,则不需要污染render方法.虽然这个答案有效,甚至可能在某些doc示例中,但如果您希望最大化效率,构造函数将更适合您.大多数反应应用程序的最大问题是渲染方法包含太多的重量,或者在其他情况下触发未经检查. (3认同)
  • 这也将在每次重新渲染时运行`bind`,这至少可以说是次优的. (2认同)
  • @matanster as Zen在这里的注释#1部分中描述了 - /sf/answers/2791472701/ - 每次渲染该组件时,将.bind放入render方法会导致新的函数声明.如果子组件使用它作为prop或类似的东西,这种行为又可以导致子组件也重新渲染.对于它的价值,JS必须在每个创建上提升该功能,因此如果您将像这样的组件作为列表项呈现数百次并且其中也有多个子项,则可能存在延迟. (2认同)

Zen*_*ter 34

由于我在多个地方看到了这些建议,我也会将我的评论转移到答案中,以提供额外的观点:

class TestComponent extends React.Component {
  constructor() {
    super();
    this.onClick = this.handleClick.bind(this);
  }

  handleClick(event) {
    const {id} = event.target;
    console.log(id);
  }

  render() {
    return (
      <div>
        <h3 id={this.props.id} onClick={this.onClick}>
          {this.props.name}
        </h3>
      </div>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

这允许:

  1. 避免不必要的束缚
  2. id以更多的React-ive方式访问和其他任何属性.

当然,上面的例子假设您收到了id作为道具,但您也可以进行必要的操作.

更新1 - 2016年11月28日

从上面的评论添加了CodePen的链接.

更新2 - 2017年3月30日

如上所述,如果您使用React.createClass定义组件,这将不起作用.你没有一个构造函数来解决这个问题.如果你不介意一点丑陋,你可以使用其他生命周期方法.

话虽如此,它是2017年.使用ES6,对吗?!

更新3 - 2017年5月12日

如果您正在使用类属性转换,那么您可以进一步简化它:

class TestComponent extends React.Component {
  onClick = (event) => {
    const {id} = event.target;
    console.log(id);
  }

  render() {
    return (
      <div>
        <h3 id={this.props.id} onClick={this.onClick}>
          {this.props.name}
        </h3>
      </div>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

更新4 - 2018年2月4日

由于bindV8中的朋友和Chacol(也许是Chakra等)的改进,你可能会更好地使用this.click.bind(this)或在传递时将其包装在箭头功能中onClick.

为什么?

之前的方法仅仅是出于性能原因而创建的,它为将函数动态注入组件的原型提供了一些可能性.

注1 - 2018年4月14日

请记住,Update 4中提到的方法仍然会引入一些性能问题,因为每次render传递都会创建一个新函数bind.反过来,这将逐渐渗透到子组件并导致不必要的重新渲染,因为函数每次都会更改.

传递内联箭头函数时会发生同样的事情.

所有其他方法,比如使用类属性,都会破坏你的继承(你应该避免,但仍然如此),原因很简单,因为目前,Babel将它们转换为"on-instance"函数,而这些函数不在原型链.

所以这:

class Person {
  printA = () => { console.log('a') }
}
Run Code Online (Sandbox Code Playgroud)

变为:

function _classCallCheck(instance, Constructor) {...abridged...}

var Person = function Person() {
  _classCallCheck(this, Person);

  this.printA = function () {
    console.log('a');
  };
};
Run Code Online (Sandbox Code Playgroud)


aik*_*eru 15

我在这里为ES6做了更新的答案:https://stackoverflow.com/a/35748912/76840

基本上,您可以使用箭头函数表达式,它具有以下优点this:

onClick={(event)=>this.viewMore(attributeId, event)}
Run Code Online (Sandbox Code Playgroud)

在此编辑中,如果您在启用stage-2的情况下使用Babel,则可以使用如下属性:

// Within your class...
viewMore = (event) => { /* ... */ }
// Within render method in your JSX
onClick = {this.viewMore}
Run Code Online (Sandbox Code Playgroud)

  • 但这不会产生在每次渲染调用中创建新函数对象的负面影响吗? (4认同)

Sag*_*b.g 5

你可以使用currying功能.

ES5:

viewMore(param) { // param is the argument you passed to the function
    return function(e) { // e is the event object that returned

    };
}
Run Code Online (Sandbox Code Playgroud)

ES6

viewMore = param => e => {
  // param is the argument you passed to the function
  // e is the event object that returned
};
Run Code Online (Sandbox Code Playgroud)

只需像这样使用它:

onClick={this.viewMore("some param")}
Run Code Online (Sandbox Code Playgroud)