react 类组件事件绑定 this 指向问题
一、React 类组件事件绑定方式:
1. 普通绑定
-
直接调用
class App extends React.Component{ // 事件函数 fn1(){ console.log('fn1') console.log(this) // undefined } render(){ <button onClick={ this.fn1 }>按钮1</button> } }- 单击
按钮1,控制台打印结果如下:
- 单击
this 指向 undefined ?
-
利用
JS类实验得到以下结果:// 定义 Star 类 class Star { thisDirection() { console.log(this); } } var star = new Star(); star.thisDirection(); // 实例调用 const x = star.thisDirection; // 保存方法 x(); // 直接调用- 控制台打印结果如下:
类中所有的方法,在局部默认开启了严格模式,它不敢指向
window所以指向了undefined。
结论:在 React 事件普通绑定中,由于直接调用了类中的方法,所以 this 指向 undefined
2. bind 绑定:
-
通过bind改变点击事件内的this指向外部组件内this (使用较多)
class App extends React.Component{ // 事件函数 fn2(){ console.log('fn2'); console.log(this); // Class } render(){ <button onClick={ this.fn2.bind(this) }>按钮2</button> } }- 单击
按钮2,控制台打印结果如下:
- 单击
-
通过在构造函数constructor内使用bind对函数内的this重定向
class App extends React.Component{ constructor(){ super() // ES6 类继承类, constructor() 里面用 this 必须调用 super() 函数 // this 指向当前类组件 // 调用公用的 属性 和 方法 必须加 this this.fn3 = this.fn3.bind(this) } // 事件函数 fn3(){ console.log('fn3'); console.log(this); // Class } render(){ <button onClick={ this.fn3 }>按钮3</button> } }- 单击
按钮3,控制台打印结果如下:
- 单击
3. 箭头函数绑定:
-
通过使用箭头函数来指向外部组件内this (使用较多)
class App extends React.Component{ // 不是真实的事件函数 fn4(){ console.log('fn4'); console.log(this); // Class } render(){ // 箭头函数才是事件函数 <button onClick={ () => this.fn4() }>按钮4</button> } }- 单击
按钮4,控制台打印结果如下:
- 单击
-
将事件函数写成箭头函数来指向外部组件内this (使用较多)
class App extends React.Component{ fn5 = () => { console.log('fn5'); console.log(this); } render(){ <button onClick={ this.fn5 }>按钮5</button> } }- 单击
按钮5,控制台打印结果如下:
- 单击
二、React 类组件事件绑定——事件对象:
-
了解了
React类组件事件绑定的 5 种方式,我们再来看看如何得到绑定事件的事件对象
1. 普通绑定
-
直接调用
class App extends React.Component{ // 事件函数 fn1(event){ console.log('fn1') console.log(this) // undefined console.log(event); // 事件对象 } render(){ <button onClick={ this.fn1 }>按钮1</button> } }- 单击
按钮1,控制台打印结果如下:
- 单击
2. bind 绑定:
-
通过bind改变点击事件内的this指向外部组件内this (使用较多)
class App extends React.Component{ // 事件函数 fn2(event){ console.log('fn2'); console.log(this); console.log(event); } render(){ <button onClick={ this.fn2.bind(this) }>按钮2</button> } }- 单击
按钮2,控制台打印结果如下:
- 单击
-
通过在构造函数constructor内使用bind对函数内的this重定向
class App extends React.Component{ constructor(){ super() // ES6 类继承类, constructor() 里面用 this 必须调用 super() 函数 // this 指向当前类组件 // 调用公用的 属性 和 方法 必须加 this this.fn3 = this.fn3.bind(this) } // 事件函数 fn3(event){ console.log('fn3'); console.log(this); console.log(event); } render(){ <button onClick={ this.fn3 }>按钮3</button> } }- 单击
按钮3,控制台打印结果如下:
- 单击
3. 箭头函数绑定:
-
通过使用箭头函数来指向外部组件内this (使用较多)
class App extends React.Component{ // 不是真实的事件函数 fn4(event){ console.log('fn4'); console.log(this); // Class console.log(event); } render(){ // 箭头函数才是事件函数 <button onClick={ (ev) => { this.fn4(ev); } }>按钮4</button> } }- 单击
按钮4,控制台打印结果如下:
- 单击
-
将事件函数写成箭头函数来指向外部组件内this (使用较多)
class App extends React.Component{ fn5 = () => { console.log('fn5'); console.log(this); console.log(event); } render(){ <button onClick={ this.fn5 }>按钮5</button> } }- 单击
按钮5,控制台打印结果如下:
- 单击
三、React 类组件事件绑定——事件传参:
-
得到了
React类组件绑定事件的事件对象,我们再来看看如何对绑定事件传参
1. 普通绑定
-
直接调用
class App extends React.Component{ render(){ <button onClick={ this.fn1 }>按钮1</button> } }-
没有 () 无法传参
-
2. bind 绑定:
-
通过bind改变点击事件内的this指向外部组件内this (使用较多)
class App extends React.Component{ // 事件函数 fn2(num,event){ console.log('fn2'); console.log(this); console.log(num); console.log(event); } render(){ <button onClick={ this.fn2.bind(this, 200) }>按钮2</button> } }- 单击
按钮2,控制台打印结果如下:
- 单击
-
通过在构造函数constructor内使用bind对函数内的this重定向
class App extends React.Component{ render(){ <button onClick={ this.fn3 }>按钮3</button> } }没有 () 无法传参
3. 箭头函数绑定:
-
通过使用箭头函数来指向外部组件内this (使用较多)
class App extends React.Component{ // 不是真实的事件函数 fn4(){ console.log('fn4'); console.log(this); // Class console.log(num); console.log(event); } render(){ // 箭头函数才是事件函数 <button onClick={ (ev) => { this.fn4(ev); } }>按钮4</button> } }- 单击
按钮4,控制台打印结果如下:
- 单击
-
将事件函数写成箭头函数来指向外部组件内this (使用较多)
class App extends React.Component{ render(){ <button onClick={ this.fn5 }>按钮5</button> } }没有 () 无法传参
总结:
一、直接绑定事件函数,会丢失
this指向,为了解决这个问题,React提供了如下方式:1.
bind绑定2. 箭头函数绑定
二、既传参又获取事件对象只有两种方式可以实现:
1. 模板里面
bind绑定事件传参2. 箭头函数作为事件函数绑定事件传参