We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
在React元素中绑定事件有两点需要注意:
React
DOM
onclick
onClick
onchange
onChange
<button onclick="clickButton()"> Click </button>
而在React元素中绑定一个点击事件变成这种形式:
<button onClick={clickButton}> // clickButton是一个函数 Click </button>
React中的事件是合成事件,并不是原生的DOM事件。
React根据W3C规范定义了一套兼容各个浏览器的事件对象。在DOM中可以通过返回false来阻止事件的默认行为,但在React中,必须显式的调用事件对象的preventDefault方法来阻止事件的默认行为。
W3C
false
preventDefault
在某些场景下如果必须使用DOM提供的原生事件,可以通过React事件对象的nativeEvent属性获取。
nativeEvent
其实,在平时的开发中,React组件中处理事件最容易出错的地方是事件处理函数中的this的指向问题,因为ES6 class并不会为方法自动绑定this到当前对象。
this
ES6 class
下面我们具体来看一下常见的三种处理this的方式:
直接在React元素中采用箭头函数定义事件的处理函数,如:
class MyComponent extends React.Component { constructor(props) { super(props); this.state = { number: 0 } } render() { return ( <button onClick={(event) => { console.log(this.state.number); }}> Click </button> ) } }
箭头函数中的this指向的是函数定义时的对象,所以可以保证this总是指向当前组件的实例对象。
当事件处理逻辑比较复杂时,如果把所有的逻辑直接写在onClick的大括号中,就会导致render函数变的臃肿,不容易直观地看出组件的UI结构,代码可读性也不好。这样,我们可以把逻辑处理封装成组件的一个方法,然后在箭头函数中调用该方法即可。
class MyComponent extends React.Component { constructor(props) { super(props); this.state = { number: 0 } } handleClick(event) { const number = ++this.state.number; this.setState({ number: number }); } render() { return ( <button onClick={(event) => { this.handleClick(event); }}> Click </button> ) } }
直接在render方法中为元素事件定义事件处理函数,最大的问题是,每次render调用时,都会重新创建一个新的事件处理函数,带来额外的性能开销,组件所处层级越低,这种开销就越大。当然,大多数情况下,这种开销是可以接受的。
直接将组件的方法赋值给元素的事件属性,同时在类的构造函数中,将这个方法的this绑定到当前对象。如:
class MyComponent extends React.Component { constructor(props) { super(props); this.state = { number: 0 }; this.handleClick = this.handleClick.bind(this); } handleClick(event) { const number = ++this.state.number; this.setState({ number: number }); } render() { return ( <button onClick={this.handleClick}> Click </button> ) } }
这种方法的好处是每次render不会重新创建一个回调函数,没有额外的性能损失。但在构造函数中,为事件处理函数绑定this,尤其是存在多个事件处理函数需要绑定时,这种模板式的代码还是会显得繁琐。
render
有时候我们还会为元素的事件属性赋值时,同时为事件处理函数绑定this,例如:
class MyComponent extends React.Component { …… render() { return ( /* 事件属性赋值和this绑定同时 */ <button onClick={this.handleClick.bind(this)}> Click </button> ) } }
使用bind会创建一个新的函数,因此这种写法依然存在每次render都会创建一个新函数的问题。但是在需要为函数传入额外的参数时,这种写法就比较方便了。
bind
class MyComponent extends React.Component { …… render() { const type = 1; return ( /* 事件属性赋值和this绑定同时 */ <button onClick={this.handleClick.bind(this, type)}> Click </button> ) } }
使用ES7的property initializers会自动为class中定义的方法绑定this。例如:
ES7
property initializers
class
class MyComponent extends React.Component { constructor(props) { super(props); this.state = { number: 0 }; } handleClick = (event) => { const number = ++this.state.number; this.setState({ number: number }); } render() { return ( <button onClick={this.handleClick}> Click </button> ) } }
这种方式既不需要在构造函数中手动绑定this,也不需要担心组件重复渲染导致的函数重复创建的问题。不过由于property initializers 这个特性还处于试验阶段,默认有些浏览器是不支持的,需要使用babel来进行支持。
babel
通过上面我们可以看到,只要处理好了React组件中函数的this绑定问题,React的事件处理就没有太大的问题了。
The text was updated successfully, but these errors were encountered:
No branches or pull requests
React中的事件处理
在
React
元素中绑定事件有两点需要注意:React
中,事件命名采用驼峰命名方式,而不是DOM
元素中的小写字母命名方式。例如onclick
要写成onClick
,onchange
要写成onChange
等。DOM
中的字符串形式。例如在DOM
中绑定一个点击事件应该写成:而在
React
元素中绑定一个点击事件变成这种形式:React
中的事件是合成事件,并不是原生的DOM
事件。React
根据W3C
规范定义了一套兼容各个浏览器的事件对象。在DOM
中可以通过返回false
来阻止事件的默认行为,但在React
中,必须显式的调用事件对象的preventDefault
方法来阻止事件的默认行为。在某些场景下如果必须使用
DOM
提供的原生事件,可以通过React
事件对象的nativeEvent
属性获取。其实,在平时的开发中,
React
组件中处理事件最容易出错的地方是事件处理函数中的this
的指向问题,因为ES6 class
并不会为方法自动绑定this
到当前对象。下面我们具体来看一下常见的三种处理
this
的方式:React事件处理的this处理
使用箭头函数
直接在
React
元素中采用箭头函数定义事件的处理函数,如:箭头函数中的
this
指向的是函数定义时的对象,所以可以保证this
总是指向当前组件的实例对象。直接在render方法中为元素事件定义事件处理函数,最大的问题是,每次render调用时,都会重新创建一个新的事件处理函数,带来额外的性能开销,组件所处层级越低,这种开销就越大。当然,大多数情况下,这种开销是可以接受的。
使用组件方法
直接将组件的方法赋值给元素的事件属性,同时在类的构造函数中,将这个方法的this绑定到当前对象。如:
这种方法的好处是每次
render
不会重新创建一个回调函数,没有额外的性能损失。但在构造函数中,为事件处理函数绑定this
,尤其是存在多个事件处理函数需要绑定时,这种模板式的代码还是会显得繁琐。有时候我们还会为元素的事件属性赋值时,同时为事件处理函数绑定
this
,例如:使用
bind
会创建一个新的函数,因此这种写法依然存在每次render
都会创建一个新函数的问题。但是在需要为函数传入额外的参数时,这种写法就比较方便了。属性初始化语法
使用
ES7
的property initializers
会自动为class
中定义的方法绑定this
。例如:这种方式既不需要在构造函数中手动绑定
this
,也不需要担心组件重复渲染导致的函数重复创建的问题。不过由于property initializers
这个特性还处于试验阶段,默认有些浏览器是不支持的,需要使用babel
来进行支持。通过上面我们可以看到,只要处理好了
React
组件中函数的this
绑定问题,React
的事件处理就没有太大的问题了。The text was updated successfully, but these errors were encountered: