react绑定事件的几种写法和理解
参考react绑定事件的几种写法 - 简书 (jianshu.com),在他的分类上写上自己的理解
错误方法
import React from 'react';
class App extends React.Component {
handleClick() {
alert('点击')
}
render() {
return (
<div>
<button onClick={this.handleClick}>click</button>
</div>
)
}
}
export default App;
handleClick并非实例对象调用,相当于如下:
class Person{
study(){
console.log(this) //测试能够访问到this
}
}
p1 = new Person()
p1.study // 可以访问到this
const x = p1.study //此时只是把Person类中的这个study函数交给了x
x() //当通过x地址访问时,study()函数并不是由实例访问的,this无法指向this实例对象,
render的时候,把handleClick这个函数直接交给了onClick,类似于上面的把study函数直接交给了x,就会导致this不指向类的实例对象,谁调用就指向谁,指向调用onClick的react对象
关注点:
- 把什么给了onClick,this指向如何?
- 不要在乎原型对象,和原型对象实例对象两者的关系无关!
方法一:最麻烦的写法,不推荐
每次页面刷新都会调用render函数
用bind(this)重新生成一个函数,其中bind的第一个参数表示把新函数的this修改为参数的this,也就是App实例对象的组件的this
此时分析一下this指向谁? 怎么执行到这里的? react实例化一个App,然后调用render进行渲染,那此时就是实例化的app = new App()执行的,此时this就是指向app
把修改过this指向的handleClick复制版交给onClick,然后就能运行正确
import React from 'react';
class App extends React.Component {
handleClick() {
alert('点击')
}
render() {
return (
<div>
<button onClick={this.handleClick.bind(this)}>click</button>
</div>
)
}
}
export default App;
方法二:在构造函数里统一绑定,不常用。
构造时绑定好,每次页面刷新都会调用render函数,无非是比第一种先绑定好,页面还没render时就直接绑定好了
构造函数也是实例对象调用的(只是说明实例对象和原型对象的this,好像也没涉及原型对象)
import React from 'react';
class App extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
alert('点击')
}
render() {
return (
<div>
<button onClick={this.handleClick}>click</button>
</div>
)
}
}
export default App;
方法三:最常见的写法。
箭头函数的this指向外侧
把一个属性名为handleClick的属性交给onClick,handleClick对应一个函数,普通函数的function不是该类实例对象调用时,this是会丢失的,而箭头函数能够在交给别人执行时,
import React from 'react';
class App extends React.Component {
constructor(props) {
super(props);
}
handleClick = () => {
alert('点击')
}
//下面的错误
handleClick = function() => {
alert('点击')
}
render() {
return (
<div>
<button onClick={this.handleClick}>click</button>
</div>
)
}
}
export default App;
class Person{
study(){
console.log(this) //测试能够访问到this
}
study2 = function(){
console.log(this) //测试能够访问到this
}
study3 = ()=>{
console.log(this)
}
}
p1 = new Person()
p1.study // 可以访问到this
const x = p1.study //此时只是把Person类中的这个study函数交给了x
x() //当通过x地址访问时,study()函数并不是由实例访问的,this无法指向this实例对象,
const x2 = p1.study2
x2() //当通过x地址访问时,study()函数并不是由实例访问的,this无法指向this实例对象,
const x3 = p1.study3
x3() //当通过x地址访问时,study()函数并不是由实例访问的,this却能够指向this实例对象,
const x3 = p1.study3
的时候study3内部的this就已经是p1了
方法四:可以传参数。
给onClick赋值时就是给绑定了一个箭头函数(e) => this.handleClick(e)
箭头函数指向外侧this,就是此时onClick赋值时,正在执行render的实例对象,
然后onClick触发时,和方法三不同,此时调用发生,执行下面的箭头函数
(e) => this.handleClick(e)
箭头函数执行内部的this.handleClick(e)
this是谁?就是刚才的:正在执行render的实例对象
那么由 正在执行render的实例对象
执行的handleClick就是实例对象调用的,this指向就没问题了
import React from 'react';
class App extends React.Component {
constructor(props) {
super(props);
}
handleClick (e) {
alert(e)
}
render() {
return (
<div>
<button onClick={(e) => this.handleClick(e)}>click</button>
</div>
)
}
}
export default App;