美文网首页
React事件系统

React事件系统

作者: 梦想成真213 | 来源:发表于2019-04-30 09:49 被阅读0次

基本使用

  • React事件名采用驼峰式写法,而不是小写

  • React事件不能直接rerurn false来阻止默认行为,必须通过preventDefault来阻止

handleClick = (e) =>{
  e.preventDefault();
}
<a href="#" onClick={e => this.handleClick(e)}>click me</a>

这里e是一个合成事件(SynthetiEvent),React根据W3C标准来定义合成事件,所以不需要担心跨浏览器的兼容问题。与原生的浏览器事件拥有同样的接口,同样是支持事件的冒泡机制,可以使用stopPropagation()preventDefault()来中断。

  • 所有事件都自动绑定到最外层,而不是直接绑定到HTML元素上,React仅仅是借鉴了这种写法而已。如果需要访问原生事件对象,可以使用nativeEvent属性。

  • 当时使用ES6 class语法定义一个组件的时候,事件处理器会成为类的一个方法:
    1.第一种回调函数中的this绑定方式:构造器内声明,通过bind

class Toggle extends React.Component {
  constructor(props){
    super(props);
    this.state = {}
    //  类的默认方法是不会绑定this的,所以通过如下方式手动绑定this
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick(){
  }
  render(){
    return <a href="#" onClick={this.handleClick}> click me</a>
  }
}

2.第二种是使用属性初始化器语法来正确的绑定回调函数的this

class Toggle extends React.Component {
  constructor(props){
    super(props);
    this.state = {}
  }
  // This syntax ensures `this` is bound within handleClick.
  // Warning: this is *experimental* syntax.
  handleClick = () => {
  }
  render(){
    return <a href="#" onClick={this.handleClick}> click me</a>
  }
}

3.第三种是在回调函数中使用箭头函数

class Toggle extends React.Component {
  constructor(props){
    super(props);
    this.state = {}
  }
  handleClick(){
  }
  render(){
    return <a href="#" onClick={e => this.handleClick(e)}> click me</a>
  }
}

向事件处理程序传递参数

有两种方式向事件处理程序传递参数
1.通过bind方式this.eventHandler.bind(this,params),类组件中监听函数这样获取参数eventHandler(e, params){}

class Toggle extends React.Component {
  constructor(props){
    super(props);
    this.state = {
       id:1
    }
  }
  handleClick(id, e){
  }
  render(){
    return <a href="#" onClick={this.handleClick.bind(this,this.state.id)}> click me</a>
  }
}
注意:通过bind方式向函数传参,在类组件中定义的监听函数,事件对象e要排在所有所传参数的最后

2.通过箭头函数的方式onClick={(e) => this.handlerEvent(e,params)} ,类组件监听函数这样获取参数 handlerEvent = (e, params) => {}

class Toggle extends React.Component {
  constructor(props){
    super(props);
    this.state = {
       id:1
    }
  }
  handleClick = (e, id) => {
  }
  render(){
    return <a href="#" onClick={ e => this.handleClick(e,this.state.id)}> click me</a>
  }
}

合成事件的实现机制

在React底层,主要对合成事件做了两件事:事件委派自动绑定

1.事件委派

[ React中的事件代理机制是:不会把事件处理函数直接绑定到真实节点上,而是把所有的事件绑定到结构的最外层,使用统一的事件监听器,这个事件监听器保存了一个所有组件内部的事件监听和处理函数的映射,当组件挂载或卸载时,只是在这个统一的事件监听器上插入或删除一些对象,当事件发生时,首先被统一的事件监听器处理,然后在映射里找到真正的事件处理函数并调用,这样做简化了事件处理和回收机制,效率也有很大提升。]

2.自动绑定

[ 在 React 组件中,每个方法的上下文都会指向该组件的实例,即自动绑定 this 为当前组件。
而且 React 还会对这种引用进行缓存,以达到 CPU 和内存的最优化。在使用 ES6 classes 或者纯
函数时,这种自动绑定就不复存在了,我们需要手动实现 this 的绑定。]

自动绑定的方式如上所示。

在React中使用原生事件

在React架构下依然是可以使用原生事件的,在componentDidMount中组件已经完成安装并在浏览器中存在真实的dom,这时就可以使用原生事件完成事件的绑定。

import React, { Component } from 'react';
class Tab extends Component {
  componentDidMount() {
    this.refs.button.addEventListener('click', e => {
      this.handleClick(e);
    });
  }
  handleClick(e) {
    console.log(e);
  }
  componentWillUnmount() {
    this.refs.button.removeEventListener('click');
  }
  render() {
    return <button ref="button">Test</button>;
  }
}

需要注意的是。使用原生事件时,在组件卸载时要手动移除事件,否则可能出现内存泄露。而使用合成事件不需要,因为React已经处理好了。

合成事件和原生事件混用

虽说合成事件系统好用,但是有时候也是需要原生事件的,比如点击一个按钮显示内容,点击空白处隐藏内容,如下示例:

import React, { Component } from 'react';
class demo extends Component {
  constructor(props) {
  super(props);
  this.state = {
    active: false,
  };

  componentDidMount() {
    //组件已经安装完成并在浏览器中是真实的dom结构
    document.body.addEventListener('click', e => {
      if (e.target && e.target.matches('div.code')) {
        return;
      }
      this.setState({
        active: false,
      });
    });
  }

  componentWillUnmount() {
    //组件卸载前要手动清掉原生事件
    document.body.removeEventListener('click');
  }

  handleClick = () => {
    this.setState({
      active: !this.state.active,
    });
  }

  handleClickQr = (e) => {
    //点击要显示的组件的时候 阻止冒泡到body,就不会触发隐藏
    e.stopPropagation();
  }

  render() {
    return (
      <div className="qr-wrapper">
        <button className="qr" onClick={this.handleClick}>click me</button>
        <div className="code" style={{ display: this.state.active ? 'block' : 'none' }} onClick={this.handleClickQr}>
          <img src="qr.jpg" alt="qr" />
        </div>
      </div>
    );
  }
}

尽量避免在React中混用合成事件和原生事件,对于无法使用合成事件的场景,才需要用原生事件来完成。

React合成事件的事件类型是Javascript原生事件类型的一个子集,并未实现全部的事件类型。

参考

https://react.docschina.org/docs/handling-events.html
https://book.douban.com/subject/26918038/

相关文章

  • React事件系统

    基本使用 React事件名采用驼峰式写法,而不是小写 React事件不能直接rerurn false来阻止默认行为...

  • React的事件

    React事件系统 事件处理程序通过 合成事件(SyntheticEvent)的实例传递,SyntheticEve...

  • 《深入React技术栈》学习笔记Ⅱ

    一、React 事件系统React 基于 Virtual DOM 实现了一个 SyntheticEvent(合成事...

  • React学习之漫谈React

    事件系统 合成事件的绑定方式 Test 合成事件的实现机制:事件委派和自动绑定。 React合成事件系统的委托机制...

  • React事件系统详解

    为了更好的阅读体验,你可以点击这里查看github原文 阅读前的测试 想点↗x关闭的同学,先花一分钟进行测试,再来...

  • react事件系统原理

    1 .我们编写的click事件,最终会被转换城fiber对象2 .fiber对象上的memoizedProps和p...

  • 浅析React之事件系统(二)

    上篇文章中,我们谈到了React事件系统的实现方式,和在React中使用原生事件的方法,那么这篇文章我们来继续分析...

  • 【web前端】什么是 React 合成事件

    概念 React 合成事件是 React 提供的一种统一的事件系统,它可以在不同浏览器中使用同一套 API 以及一...

  • react 对象池解读

    前言 在学习 React 事件系统的时候,在事件分发的 dispatch方法发现了调用了一个 getPooled ...

  • 【React进阶系列】史上最全React事件机制详解

    框架总览 ? DOM事件流的三个阶段 ? 关于React事件的疑问? React事件绑定机制? React事件和原...

网友评论

      本文标题:React事件系统

      本文链接:https://www.haomeiwen.com/subject/xqfngqtx.html