Skip to content

Latest commit

 

History

History
138 lines (108 loc) · 4.68 KB

【译】快速起步-事件处理.md

File metadata and controls

138 lines (108 loc) · 4.68 KB
title date react version
快速起步-事件处理
2017-04-18 09:58:04 -0700
15.5.0

事件处理

使用React元素处理事件和DOM元素上的事件非常相似。但还是有一些语法上的不同:

  • React 的事件是小驼峰命名的,不是全小写命名的。
  • 可以在JSX中传递函数作为事件处理器,而不是字符串。

例如:

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

在React中略微不同:

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

另一个不同是,不能通过 return false 来阻止默认行为。必须要明确使用 preventDefault 。例如,在HTML中,要想阻止a标签的默认行为,可以如下写:

<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 的时候,通常不需要调用 addEventListener 来给DOM元素添加事件。而是在元素最初渲染时提供一个监听器。

当你在使用 ES6 class 定义组件时,一个常见的模式是将事件处理程序定义为类上的一个原型方法。例如,Toggle 渲染了一个可以在 "ON" 和 "OFF" 之间切换的按钮:

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

    // 必要的绑定,让 `this` 在回调中可用。
    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')
);

CodePen Demo

您必须要注意JSX回调中 this 的含义。在JavaScript中,默认情况下,类方法不是 bound 的。如果你传递处理函数给 onClick 时忘记了绑定 thisthis.handleClick,那么当函数被调用时,this 将会是 undefined

这不是React特定的行为,它是 JavaScript中函数如何工作 的一部分。通常,如果你引用了没有 () 的方法(方法引用),比如 onClick={this.handleClick},那么你需要先 bind(this)

如果调用 bind 让你觉得很繁琐,还有两种方法可以解决这个问题。如果你在使用实现性质的语法 属性初始化,你可以使用属性初始化来正确的绑定回调的 this

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` 在 handleClick中指向正确
    return (
      <button onClick={(e) => this.handleClick(e)}>
        Click me
      </button>
    );
  }
}

这个语法的问题是,每次 LoggingButton 渲染时,都会创建一个不同的回调函数。大多数情况下,这都没啥问题。但是,如果这个回调函数会传递给层次更低的组件,那么可能会导致这些组件进行额外的渲染。我们通常建议在构造函数中使用绑定,或者使用属性初始化语法来避免这个问题。