React技术文档(二)

发布时间 2023-07-27 15:47:44作者: 小小一个钰

React技术文档(二)

事件绑定

事件绑定的写法

在react中于需要绑定事件的节点上采用on+事件名驼峰写法定义,如onBlur onClick onInput 事件命名法

import React, { Component } from 'react'
export default class App extends Component {
  add=()=>{
    console.log('add');
  }
  render() {
    function active(e) {
      console.log(e);
    }
    return (
      <div>
        <input onBlur={active} />
        <button onClick={this.add}>add</button>
      </div>
    )
    
  }
}

直观来讲,add()函数和active()函数同为函数,却有着截然不同的区别,观察发现,add()函数定义于render()方法外部,active()函数定义于render()方法内部,那他们之间到底有什么不同呢?

  • 生命周期和作用域:

    我们知道,类组件中通过定义的方法,我们可以叫做类方法,所以它具备类组件的作用域和生命周期,我们使用this关键字就可以访问该类上的实例属性及方法;

    反之,被render()局部定义的函数执行只存在于render()这个方法执行区间内,在外部不可对其进行访问,仅限于作用域内可使用,同时,render()中的函数不具备类的组件特性,因此它的this范围不在类上,而在render()范围内,无法访问类的实例属性及方法

  • 在特定的场景使用:

    定义在类上的方法,其功能更多,能够进行具备类方法特征的更多操作;

    那我们在什么情况下使用render()局部函数呢?

    在一些用于具体的事件回调逻辑中,如在输入框失去焦点时触发事件,是特定的执行操作,并且仅在事件触发时被调用

事件绑定的几种方式

import React, { Component } from 'react'
export default class App extends Component {
  a = 100
  add=()=>{
    console.log('add',this.a)
  }
  _add(){
    console.log('_add',this.a)
  }
  render() {
    return (
      <div>
        <input />
        {/* 四种不同的事件调用方法 */}
        <button onClick={()=>{ 
          console.log('add1',this.a);
        }}>add1</button>
        <button onClick={this.add}>add2</button>
        <button onClick={this._add}>add3</button>
        <button onClick={()=>{this.add()}}>add4</button>
      </div>
    ) 
  } 
}

在上述几种不同的事件调用方法中,this的指向问题及如何改变this指向是重中之重

  • 当使用箭头函数直接作为事件绑定处理程序时,this便指向类的实例,很明显此处的this指向为App实例
<button onClick={()=>{ 
  console.log('add1',this.a);
}}>add1</button>
  • add()函数以箭头函数定义,它位于类的方法中,因此通过this.add可以找到类上的add()函数,由于箭头函数this指向该类的实例,因此能够在add()函数内部通过this访问类上的属性和方法
add=()=>{
    console.log('add',this.a)
  }
<button onClick={this.add}>add2</button>
  • _add()函数是普通函数,其this未定义,因此无法访问类中的属性a,若想改变this指向,可以用过call() | apply() | bind()实现,但是由于我们是事件调用,需要手动触发函数调用,call() | apply() 为自动触发,因此这里选择bind()最为合适
_add(){
    console.log('_add',this.a)
}
<button onClick={this._add.bind(this)}>add3</button>
  • 对于在箭头函数中调用事件,其this指向类实例对象,可以访问在类中定义的属性和方法
add=()=>{
 console.log('add',this.a)
}
<button onClick={()=>{this.add()}}>add4</button>

综上:在react事件处理中,更推荐使用箭头函数

事件绑定原理

与原生事件绑定原理不同,在react中事件绑定并不是绑定在DOM节点上,而是采用事件代理的模式

具体是怎样的代理模式呢?

image-20230727141307266

在开发者模式下我们可以看到,按钮add1所在事件为button,接下来我们将button事件移除,在此点击add1调用事件,发现事件还是继续被调用

image-20230727141211204

这便说明,事件点击并非绑定在事件本身或者通过事件本身触发,而是通过事件代理实现,所有的节点事件都通过代理的方式绑定为根事件上,即上图.text上,那么此时我们将.text事件删除,再次点击按add1发现事件不再被调用,即可证明事件代理原理

image-20230727141644738

在 React 中,事件绑定通过使用代理机制来处理。这种代理机制的作用有以下几个方面:

  • 性能优化:

    react使用事件代理|事件委托方式处理事件,在整个组件根节点上监听事件,这样就会节省事件监听器的使用数量,有助于降低内存的消耗提高性能。react中使用一个统一的事件监听器管理所有组件的事件处理逻辑

  • 动态更新:

    在react中事件的绑定其实是存在于虚拟DOM上,因此当组件的状态或属性发生动态变化时,react会自动更新需要更新的部分,事件也会自动更新,免去了手动更新操作

  • 便于事件处理:

    在react中我们可以使用类似原生事件的绑定方式, 并且提供了SyntheticEvent(合成事件)对原生事件进行分装,更方便处理事件功能