react事件

1.事件机制

大体来说,react的事件机制分为两部分,一个是事件注册,一个是事件分发

  • 事件注册部分: 所有的事件都是注册到document上
  • 事件分发部分: 所有的事件由同意的回调函数(dispatchEvent)来执行事件分发;首先生成合成事件(Event) ,同一类型的事件(比如onclick事件)会合成一个事件(Event),dom上所有绑定的onclick的回调函数都会按照顺序(事件冒泡或者事件捕获)放到Event._dispatchListeners这个数组里,依次执行里面的函数

2.阻止默认事件

我们都知道,a标签是带有默认跳转事件的(当a标签的href属性为空时,默认是当前页面的地址,所以点击会刷新当前页面),如果我们在a标签上注册一个点击事件,既会触发点击事件,也会触发a标签的跳转事件
使用 e.preventDefault() 阻止默认事件
例如:

  function stopDefaultEvent(e){
    e.preventDefault()
    console.log('stop event');
    
  }
  return (
    <div className="App">
       <a href="" onClick= { stopDefaultEvent }>事件处理</a>
    </div>
  );

3.尽量不要使用 addEventListener

尽量不要使用原生js注册事件的方式addEventListener
为了提高框架的性能,React 通过 DOM 事件冒泡,只在 document 节点上注册原生的 DOM 事件,React 内部自己管理所有组件的事件处理函数,以及事件的冒泡、捕获。
所以说,如果你通过 addEventListener 注册了某个 DOM 节点的某事件处理函数,并且通过 e.stopPropagation(); 阻断了事件的冒泡或者捕获,那么该节点下的所有节点上,同类型的 React 事件处理函数都会失效。

例如:

class CounterLink extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    }
    this.handleClick = this.handleClick.bind(this);
  }
  componentDidMount() {
    document.querySelector('.my-link').addEventListener('click', (e) => {
      console.info('raw click');
      e.stopPropagation();
    })
  }
  handleClick(e) {
    e.preventDefault();
    console.info('react click');
    this.setState({ count: this.state.count + 1 });
  }
  render() {
    return (
      <div className="my-link">
        <a href="#" onClick={this.handleClick}>Clicked me {this.state.count} times.</a>    
      </div>
    )
  }
}
ReactDOM.render(<CounterLink/>, document.querySelector("#root"));

虽然设置的链接的点击事件,但是它却执行不了

4.react注册事件的几种方式

  • 1.bind this
    当你使用 ES6 class 语法定义一个组件的时候,通常的做法是将事件处理函数声明为 class 中的方法
import React from "react";

export default class Home extends React.Component {
  constructor(props) {
    super(props);
    this.toWeather = this.toWeather.bind(this);
  }
  toWeather() {
    this.props.history.push("/weather");
  }
  render() {
    return (
      <div>
        <span onClick={this.toWeather}>go weather</span>
      </div>
    );
  }
}
  • 2.class fields
    如果你正在使用实验性的 public class fields 语法,你可以使用 class fields 正确的绑定回调函数:
import React from "react";

export default class Home extends React.Component {
  toWeather = () => {
    this.props.history.push("/weather");
  };
  render() {
    return (
      <div>
        <span onClick={this.toWeather}>go weather</span>
      </div>
    );
  }
}
  • 3.箭头函数
import React from "react";

export default class Home extends React.Component {
  toWeather() {
    this.props.history.push("/weather");
  }
  render() {
    return (
      <div>
        <span onClick={() => this.toWeather()}>go weather</span>
      </div>
    );
  }
}
  • 4.箭头函数带来的性能问题:

箭头函数语法问题在于每次渲染 LoggingButton 时都会创建不同的回调函数。在大多数情况下,这没什么问题,但如果该回调函数作为 prop 传入子组件时,这些组件可能会进行额外的重新渲染。我们通常建议在构造器中绑定或使用 class fields 语法来避免这类性能问题。

posted @ 2019-12-05 18:25  zoo-x  阅读(239)  评论(0)    收藏  举报