Skip to content

Commit

Permalink
add react hanlding events
Browse files Browse the repository at this point in the history
Former-commit-id: cb4b296
Former-commit-id: f508dc7
  • Loading branch information
hstarorg committed Apr 18, 2017
1 parent 5f90dce commit a81ce33
Showing 1 changed file with 138 additions and 0 deletions.
138 changes: 138 additions & 0 deletions React面面观/【译】快速起步-事件处理.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
---
title: 快速起步-事件处理
date: 2017-4-18 16:58:04
react version: 15.5.0
---

# 事件处理

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

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

例如:

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

在React中略微不同:

```js{1}
<button onClick={activateLasers}>
Activate Lasers
</button>
```

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

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

但是在React中,你必须这样写:

```js{2-5,8}
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}
return (
<a href="#" onClick={handleClick}>
Click me
</a>
);
}
```

在这里, `e` 是一个合成事件。`React` 根据 [W3C 标准](https://www.w3.org/TR/DOM-Level-3-Events/) 定义了这些合成事件,所以你不需要担心浏览器兼容性问题。查看 [SyntheticEvent](https://facebook.github.io/react/docs/events.html) 了解更多。

在使用 `React` 的时候,通常不需要调用 `addEventListener` 来给DOM元素添加事件。而是在元素最初渲染时提供一个监听器。

当你在使用 [ES6 class](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes) 定义组件时,一个常见的模式是将事件处理程序定义为类上的一个原型方法。例如,`Toggle` 渲染了一个可以在 "ON" 和 "OFF" 之间切换的按钮:

```js{6,7,10-14,18}
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](http://codepen.io/gaearon/pen/xEmzGg?editors=0010)

您必须要注意JSX回调中 `this` 的含义。在JavaScript中,默认情况下,类方法不是 [bound](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind) 的。如果你传递处理函数给 `onClick` 时忘记了绑定 `this``this.handleClick`,那么当函数被调用时,`this` 将会是 `undefined`

这不是React特定的行为,它是 [JavaScript中函数如何工作](https://www.smashingmagazine.com/2014/01/understanding-javascript-function-prototype-bind/) 的一部分。通常,如果你引用了没有 `()` 的方法(方法引用),比如 `onClick={this.handleClick}`,那么你需要先 `bind(this)`

如果调用 `bind` 让你觉得很繁琐,还有两种方法可以解决这个问题。如果你在使用实现性质的语法 [属性初始化](https://babeljs.io/docs/plugins/transform-class-properties/),你可以使用属性初始化来正确的绑定回调的 `this`

```js{2-6}
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](https://github.com/facebookincubator/create-react-app) 中,这个语法是默认启用的。

如果你不想使用属性初始化语法,你还可以在回调中使用 [箭头函数](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions)

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

0 comments on commit a81ce33

Please sign in to comment.