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节点上,而是采用事件代理的模式
具体是怎样的代理模式呢?
在开发者模式下我们可以看到,按钮add1
所在事件为button
,接下来我们将button
事件移除,在此点击add1
调用事件,发现事件还是继续被调用
这便说明,事件点击并非绑定在事件本身或者通过事件本身触发,而是通过事件代理实现,所有的节点事件都通过代理的方式绑定为根事件上,即上图.text
上,那么此时我们将.text事件删除,再次点击按add1
发现事件不再被调用,即可证明事件代理原理
在 React 中,事件绑定通过使用代理机制来处理。这种代理机制的作用有以下几个方面:
-
性能优化:
react使用事件代理|事件委托方式处理事件,在整个组件根节点上监听事件,这样就会节省事件监听器的使用数量,有助于降低内存的消耗提高性能。react中使用一个统一的事件监听器管理所有组件的事件处理逻辑
-
动态更新:
在react中事件的绑定其实是存在于虚拟DOM上,因此当组件的状态或属性发生动态变化时,react会自动更新需要更新的部分,事件也会自动更新,免去了手动更新操作
-
便于事件处理:
在react中我们可以使用类似原生事件的绑定方式, 并且提供了
SyntheticEvent
(合成事件)对原生事件进行分装,更方便处理事件功能