-
Notifications
You must be signed in to change notification settings - Fork 67
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
138 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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` 渲染时,都会创建一个不同的回调函数。大多数情况下,这都没啥问题。但是,如果这个回调函数会传递给层次更低的组件,那么可能会导致这些组件进行额外的渲染。我们通常建议在构造函数中使用绑定,或者使用属性初始化语法来避免这个问题。 |