React:Event

React中给React Element添加事件 和 在DOM中添加事件 很类似。区别是:

1.React中事件特性用驼峰写法,比如onClick(在HTML中事件特性也是特性而已,按标准都该小写。React Element中的HTML特性都是驼峰写法,事件特性也不例外)。

2.React中事件特性传入的是一个JSX语法的函数onClick={someFun},而DOM事件特性传入的是字符串。

 1 function ActionLink() {
 2   function handleClick(e) {
 3     e.preventDefault();
 4     console.log('The link was clicked.');
 5   }
 6 
 7   return (
 8     <a href="#" onClick={handleClick}>
 9       Click me
10     </a>
11   );
12 }

文档指出,在DOM的事件特性中我们可以给其字符串添加“return false;”阻止默认行为,但是React中不行,得在执行代码中显示e.preventDefault;(不过这没关系,绝大多数时候我们都是不会加return false啦。。)

文档同时指出,在React中,我们不需要对生成的DOM使用addEventListener方法,直接在React Element初次渲染的时候提供一个事件监听器就好了,做法是上面代码第8行那样直接在JSX中绑定事件。

事件对象e是一个synthetic event,synthetic 本意是合成的、综合的,这里可以理解为包装好的跨浏览器的事件对象,可以直接使用。当我们写类组件的时候,一个通用的做法是将事件句柄作为类的一个方法。

如下:

 1 class Toggle extends React.Component {
 2   constructor(props) {
 3     super(props);
 4     this.state = {isToggleOn: true};
 5   
 6     // This binding is necessary to make `this` work in the callback。当方法被类及其实例之外的第三方调用时,因未绑定,只值undefined
 7     this.handleClick = this.handleClick.bind(this);
 8   }
 9 
10   handleClick() {
11     this.setState(prevState => ({
12       isToggleOn: !prevState.isToggleOn
13     }));
14   }
15 
16   render() {
17     return (
18       <button onClick={this.handleClick}>
19         {this.state.isToggleOn ? 'ON' : 'OFF'}
20       </button>
21     );
22   }
23 }

但是由于处理程序是定义在Class中的,在DOM中调用时,必须注意this的指向。如果是读取组件的内部变量,this应当绑定组件实例。

文档提高另外两种将this指向组件的方法:

第一种是所谓的 property initializer syntax,定义方法时,将箭头函数赋值给方法名:

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

第二种是:

 <button onClick={(e) => this.handleClick(e)}>

第二种是不推荐的,因为button渲染都会重新创建一个callback,当把callback作为props传给底层组件时,可能导致额外的渲染。推荐前面两种方式。

至此,创建稍微复杂的组件还是用Class模式。