React文档1-6_事件处理

2018.9.14 星期五 22:39

React 元素的事件处理和 DOM元素的很相似。但是有一点语法上的不同:

  • React事件绑定属性的命名采用驼峰式写法,而不是小写。
  • 如果采用 JSX 的语法你需要传入一个函数作为事件处理函数,而不是一个字符串(DOM元素的写法)

在 React 中另一个不同是你不能使用返回 false 的方式阻止默认行为。你必须明确的使用 preventDefault。

1
2
3
4
5
6
7
8
9
10
11
12
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}

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

e 是一个合成事件。React 根据 W3C spec 来定义这些合成事件,所以你不需要担心跨浏览器的兼容性问题

使用 React 的时候通常你不需要使用 addEventListener 为一个已创建的 DOM 元素添加监听器。你仅仅需要在这个元素初始渲染的时候提供一个监听器。
当你使用 ES6 class 语法来定义一个组件的时候,事件处理器会成为类的一个方法。例如,下面的 Toggle 组件渲染一个让用户切换开关状态的按钮:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};

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

}

handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
// $2 :使用实验性的属性初始化器语法
// This syntax ensures `this` is bound within handleClick.
// Warning: this is *experimental* syntax.
handleClick = () => {
console.log('this is:', this);
}
// $3: 回调函数中使用 箭头函数
// $3 This syntax ensures `this` is bound within handleClick
return (
<button onClick={(e) => this.handleClick(e)}>
Click me
</button>
);

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

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

你必须谨慎对待 JSX 回调函数中的 this,类的方法默认是不会绑定this 的。如果你忘记绑定 this.handleClick 并把它传入 onClick, 当你调用这个函数的时候 this 的值会是 undefined。
$_PS: 注意这里是 回调函数 中,参见最后的$PS 。
这并不是 React 的特殊行为;它是函数如何在 JavaScript 中运行的一部分。通常情况下,如果你没有在方法后面添加 () ,例如 onClick={this.handleClick},你应该为这个方法绑定 this.

如果使用 bind 让你很困惑,这里有两种方式可以解决。
$2: 如果你正在使用实验性的属性初始化器语法,你可以使用属性初始化器来正确的绑定回调函数:

$3: 如果你没有使用属性初始化器语法,你可以在回调函数中使用 箭头函数:
使用这个语法有个问题就是每次 LoggingButton 渲染的时候都会创建一个不同的回调函数。在大多数情况下,这没有问题。然而如果这个回调函数作为一个属性值传入低阶组件,这些组件可能会进行额外的重新渲染。我们通常建议在构造函数中绑定或使用属性初始化器语法来避免这类性能问题。

将参数传递给事件处理程序

$_PS: org.cn 是没有该段落的

1
2
3
// 分别使用 arrow functions 和 Function.prototype.bind 。
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

上面两个例子中,参数 e 作为 React 事件对象将会被作为第二个参数进行传递。
通过箭头函数的方式,事件对象必须显式的进行传递,
但是通过 bind 的方式,事件对象以及更多的参数将会被隐式的进行传递。

$_PS: 函数如何在 JavaScript 中运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
var myObj = {
specialFunction: function () {

},

anotherSpecialFunction: function () {

},

getAsyncData: function (cb) {
cb();
},

render: function () {
var that = this;
this.getAsyncData(function () {
that.specialFunction();
that.anotherSpecialFunction();
});
}
};
myObj.render();
// Uncaught TypeError: Object [object global] has no method 'specialFunction'
// rewrite
render: function () {
this.getAsyncData(function () {
this.specialFunction();
this.anotherSpecialFunction();
}.bind(this));
}

2018.9.14 星期五 23:11

knowledge is no pay,reward is kindness
0%