Handling Events(事件处理)

React中的事件处理跟dom中的事件处理是差不多的,只不过在语法上面有几处不同:

_ 1、react事件处理属性命名采用驼峰式命名规则,而不是全部大小写,例如,react采用onClick,而dom中采用的是onclick;

_ 2、在jsx你需要传递一个函数作为事件监听器,而不是一个字符串,如:

  1. function fn(){
  2. alert('我点击了div');
  3. };
  4. const element = <div onClick={fn}>点击</div>;
  5. ReactDOM.render(
  6. element,
  7. document.getElementById('root')
  8. );

我们先来看一个例子,看下它们之间有什么不同!

首先在html中:

  1. <button onclick="activalteLasers()">
  2. Activate Lasers
  3. </button>

同样的目的,在react中稍稍有点不同:

  1. <button onClick={activateLasers}>
  2. Activate Lasers
  3. </button>

还有一个不同就是,你不能像普通html那样用return false来阻止某些浏览器默认行为,你必须明确的调用preventDefault方法。例如,在普通的html中,我们可以为a标签绑定点击事件,用return false来阻止默认的页面跳转行为,于是你的代码是这样的:

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

但是在react中,你得这样写:

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

这里注意一下,参数e是一个事件合成物,react定义这个e是按照w3c标准实现,所以你不用担心跨浏览器兼容问题。你可以从这里得到更多react对e的信息。

在使用react的过程中,你可以不用在添加一个元素之后,然后再使用addEventListener方法为这个元素添加事件监听器。取而代之,你可以在元素调用render方法的时候提供一个事件监听器就好了。

在使用“类式”方式构建一个组件的时候,一个通常的模式就是把事件处理定义成组件的一个方法。例如,下面的Toggle组件,有个一个按钮用来在“on”和“off”状态之间切换:

  1. class Toggle extends React.Component{
  2. constructor(props){
  3. super(props);
  4. this.state = {isToggleOn : true};
  5. //这个绑定上下文的代码是有必要的,因为这样可以确保你调用当前方法总是在保证上下文是当前对象
  6. this.handleClick = this.handleClick.bind(this);
  7. };
  8. handleClick(){
  9. this.setState(prevState=>({
  10. isToggleOn : !prevState.isToggleOn
  11. }));
  12. };
  13. render(){
  14. return (
  15. <button onClick={this.handleClick}>
  16. {this.state.isToggleOn?'ON':'OFF'}
  17. </button>
  18. );
  19. };
  20. };
  21. ReactDOM.render(
  22. <Toggle />,
  23. document.getElementById('root')
  24. );

你必须小心注意组件里面方法的“this”绑定问题,因为在类里面,这个是默认没有绑定上下文的,所以如果你忘记绑定了哈,那么它的值将是undefined。

这个问题不是react独有的,而是普遍存在的,你可以在how functions work in JavaScript查找到相关线索。所以如果你没有在定义组件的时候直接在方法后面加上圆括号直接调用的话,那么你就必须进行上下文绑定处理。

当然了,如果你觉得进行绑定这一步会使你感觉很恼火的话,那么有两种方法可以避免:

  1. class LoggingButton extends React.Component{
  2. handleClick = () => {
  3. console.log('this is:',this);
  4. }
  5. render(){
  6. return (
  7. <button onClick={this.handleClick}>
  8. Click me
  9. </button>
  10. );
  11. };
  12. };

这种方式已经在你使用Create React App搭建react环境的时候默认支持。

  1. class LoggingButton extends React.Component{
  2. handleClick(){
  3. console.log('this is:',this);
  4. };
  5. render(){
  6. //这种方法可以使得帮当前对象“this”绑定到handleClick里面
  7. return (
  8. <button onClick={(e)=>this.handleClick(e)} >
  9. Click me
  10. </button>
  11. );
  12. };
  13. };

这种方式有个不同的地方就是,每次渲染LoggingButton的时候都会调用一次回调,在大多数情况下,这样做没有什么问题,但是当这个方法传递给下一级的组件做props属性时,那么这些下一级的组件将不会no-rendering。我们通常推荐你用第一种方法来避免这种类型的问题!