5.Handing Event(处理事件)

React版本:15.4.2
**翻译:xiyoki **

使用React元素处理事件与处理DOM元素上的事件非常相似。有一些句法差异:

  • React事件使用camelCase命名,而不是小写命名。

  • 使用JSX传递一个函数作为事件处理程序,而不是一个字符串。

例如,HTML:

<button onclick="activateLasers()">
  Activate Lasers
</button>

在React中略有不同:

<button onClick={activateLasers}>
  Activate Lasers
</button>

另一个区别是,在React中你不能通过返回false来阻止默认行为。你必须明确调用preventDefault。例如,对于普通的HTML,为了阻止链接默认打开新页面的行为,你可以这样写:

<a href="#" onclick="console.log('The link was clicked.'); return false">
  Click me
</a>

在React中,应该这样写:

function ActionLink() {
  function handleClick(e) {
    e.preventDefault();
    console.log('The link was clicked.');
  }

  return (
    <a href="#" onClick={handleClick}>
      Click me
    </a>
  );
}

这里的e是合成的事件。React根据W3C规范定义了这些合成事件,所有你不必担心跨浏览器的兼容性。请参阅 SyntheticEvent参考指南了解更多信息。

当使用React时,你通常不需要在一个DOM元素创建之后,通过调用addEventListener给该元素添加监听程序。取而代之的是,在这个元素最初被渲染时为其添加监听函数。

当你使用ES6类定义一个组件,事件处理程序的常见模式是:事件处理程序必须是类中的一个方法。例如,Toggle组件渲染一个按钮,让用户在‘开’和‘关’这两个状态间进行切换。

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};

    // This binding is necessary to make `this` work in the callback
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState(prevState => ({
      isToggleOn: !prevState.isToggleOn
    }));
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

ReactDOM.render(
  <Toggle />,
  document.getElementById('root')
);

你必须小心this在JSX回调中的含义。在Javascript中,类方法默认不绑定。如果你忘记绑定this.handleClick,并将它传递给onClick,当函数实际调用时,this将变成undefined

这不是React特定的行为,而是函数如何在javascript中工作的一部分。一般来说,如果你引用一个不带()的方法,例如onClick={this.handleClick},你应该绑定该方法。

如果调用bind惹恼了你,有两种方法可以解决这个问题。如果你使用的是实验性质的初始化语法,你可以使用属性初始化正确绑定回调:

class LoggingButton extends React.Component {
  // This syntax ensures `this` is bound within handleClick.
  // Warning: this is *experimental* syntax.
  handleClick = () => {
    console.log('this is:', this);
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        Click me
      </button>
    );
  }
}

这个语法在Create React App中是默认启用的。

如果你不使用属性初始化语法,你可以在回调中使用一个箭头函数:

class LoggingButton extends React.Component {
  handleClick() {
    console.log('this is:', this);
  }

  render() {
    // This syntax ensures `this` is bound within handleClick
    return (
      <button onClick={(e) => this.handleClick(e)}>
        Click me
      </button>
    );
  }
}

这种语法的问题是,每当LoggingButton渲染时,不同的回调被创建。在大多数情况下,这是可以的。然而,如果这个回调作为一个prop传递给较低的组件,这些组件可能会做额外的重新渲染。我们一般建议在构造函数中使用绑定或使用属性初始化语法,以避免这种性能问题。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容