React躬行记(6)——事件

  React在原生事件的基础上,重新设计了一套跨浏览器的合成事件(SyntheticEvent),在事件传播、注册方式、事件对象等多个方面都做了特别的处理。

一、注册事件

  合成事件采用声明式的注册方式,类似于设置HTML属性,但有两点不同:

(1)事件要采用小驼峰的命名法,而不是全部小写,例如onclick要写成onClick。

(2)在JSX中的事件处理程序是一个函数引用,而不是一段字符串,如下代码所示,其中handle()是一个函数。

<button onclick="handle()">提交button>
<button onClick={handle}>提交button>

  两个

); } }

  当点击提交按钮时,在控制台输出的顺序是“body”、“html”、“子元素”、“父元素”。在React的合成事件中,也会包含一个事件对象(例如handle1()函数中的e参数)。如果要停止冒泡传播,那么可以在相应的事件处理程序中调用e.stopPropagation()。

三、事件对象

  React基于W3C规范对事件对象进行了一层封装,不仅保证了浏览器的兼容性,还提供了一个访问原生事件对象的入口(即调用自身的nativeEvent属性)。注意,在合成事件中阻止元素的默认行为,不能用返回false的方式,得调用事件对象的preventDefault()方法。

  合成事件是被池化的,在执行完事件处理程序后,其参数(即事件对象)的属性将会被丢弃,例如通过定时器异步调用事件对象的type属性,如下所示。

class Btn extends React.Component {
  handle(e) {
    console.log(e.type);         //"click"
    setTimeout(function() {
      console.log(e.type);       //null
    }, 0);
  }
  render() {
    return ;
  }
}

  点击提交按钮,在控制台首先会输出“click”,然后再输出null。如果想要保持事件对象的属性,那么可以调用它的persist()方法。继续上一个例子,只要在handle()方法中加一句e.persist(),如下代码所示,就能在定时器中输出“click”。

handle(e) {
  console.log(e.type);           //"click"
  setTimeout(function() {
    console.log(e.type);         //"click"
  }, 0);
  e.persist();
}

四、this

  事件处理程序中的this不会自动绑定,即默认是没有指向的。在下面的例子中,点击提交按钮,会先触发注册的handle()方法,然后在方法内输出的this的值是undefined。

class Btn extends React.Component {
  handle() {
    console.log(this);           //undefined
  }
  render() {
    return ;
  }
}

  有两种方式可以解决this指向的问题,分别是箭头函数和bind()方法。

1)箭头函数

  将事件处理程序改成箭头函数的形式,就能纠正this的指向,如下代码所示。

class Btn extends React.Component {
  handle() {
    console.log(this);         //Btn实例
  }
  render() {
    return ;
  }
}

  箭头函数是不包含this的,在其内部使用的this是从上一层的作用域中继承而来的,其指向的是函数声明时所在的对象,即当前组件的实例,注意,像上面的; } }

2)bind()

  为事件处理程序调用bind()方法,同样也能纠正this的指向,如下代码所示。

class Btn extends React.Component {
  handle() {
    console.log(this);         //Btn实例
  }
  render() {
    return ;
  }
}

  函数的bind()方法能创建一个绑定指定对象的函数,在上面的render()方法中,传递给bind()方法的this,其指向的正是当前组件的实例。除了在元素的属性中调用bind()方法之外,还可以将其移到组件的构造函数中,如下所示。

class Btn extends React.Component {
  constructor(props) {
    super(props);
    this.handle = this.handle.bind(this);
  }
  handle() {
    console.log(this);         //Btn实例
  }
  render() {
    return ;
  }
}

五、事件处理程序的参数

  事件处理程序默认会接收一个事件对象,如果要向其传递额外的参数,那么可以通过两种方式实现。

  第一种是用箭头函数,如下代码所示,显式地将所有参数传递给事件处理程序。

class Btn extends React.Component {
  handle(e, name) {
    console.log(e, name);
  }
  render() {
    return ;
  }
}

  第二种是用bind()方法,如下代码所示,事件对象会被隐式的传递过去,并且必须位于事件处理程序参数列表的最后。

class Btn extends React.Component {
  handle(name, e) {
    console.log(name, e);
  }
  render() {
    return ;
  }
}

 

你可能感兴趣的:(React躬行记(6)——事件)