React 事件绑定的一些问题。例如:为什么一定要用 bind 或者 箭头函数

问题一:为啥要用bind 和 箭头函数

刚接触React,基本上都会遇到一个问题:就是在事件处理函数里面用到了this,但是 这个this是undefined,导致报错。

然后这个问题的原因,常见说法是:“React事件处理函数是没有默认绑定this的”,虽然没有错,但是没有get到真正的点。

原因:

  首先,这是 JavaScript 函数和this工作原理导致的,并不是React的问题,事件处理的那个 props——onClick 接收到了函数,却不知道执行上下文

  this是当前函数运行所在的环境,也就是总是指向函数运行所在的那个对象。

解决方案:

  1、使用bind绑定

  2、使用箭头函数。 

先看看关于this的一个例子

 1 var obj = {
 2     foo: function() {
 3         console.log(this)
 4     }      
 5 }
 6 
 7 var foo = obj.foo
 8 
 9 obj.foo()  // 打印结果是  obj对象
10 foo()      // 打印结果是  undefined

再看一个用 class 模拟一个和React相似的例子:

 1 let onClick = null
 2 
 3 class CustomReact {
 4     handleClick() {
 5         console.log(this)
 6     }
 7     render() {  
 8      onClick = this.handleClick 
 9    } 
10 } 
11 var c = new CustomReact() 
12 c.render() 
13 
14 onClick() // 打印出来的是 undefined

因为在赋值的时候,丢失了它的 执行上下文,只赋值过去了一个普通函数

所以我们只有“包装”一个含有执行上下文的函数,然后赋值给新变量,那么这个变量执行的时候就能找到它的执行上下文。

“包装”的方法就有 bind 和 箭头函数

然后用处理React的方法,用bind稍作修改

/* 把 onClick = this.handleClick
*  改成 onClick = this.handleClick.bind(this)
*  或者 把 handleClick 改为 handleClick = () => {}
*  然后再 执行 onClick ,打印的就会是CustomReact 对象
*/

  

问题二: class 中,handleClick() {}  和 handleClick = () => {} 的区别

区别一:前者是方法的简写,所以还是function函数,后者是箭头函数

区别二:前者是原型方法,后者是实例方法。

 1 class Test {
 2       instanceFunc = () => {}  // 实例方法
 3   
 4       protoFunc() {} // 原型方法。这是ES6对象方法的简写
 5  
 6 }
 7 
 8 // 上面代码等同于 
 9   
10 function Test() {
11     this.instanceFunc = function () {}
12 }
13 
14 Test.prototype = {
15     constructor: Test
16     protoFunc: function() {}
17 }

问题三:在render 中绑定 this 和 在外面绑定的区别?

在 render 中绑定this的时候,不管bind还是箭头函数都会新创建一个函数,这会可能会破坏它本身严格比较的优化

React 事件绑定的一些问题。例如:为什么一定要用 bind 或者 箭头函数

React 事件绑定的一些问题。例如:为什么一定要用 bind 或者 箭头函数

相比较于这两种,更推荐使用下面两种用法

1、

this.handleClick = this.handleClick.bind(this)

.....

onClick={this.handleClick}

2、

handleClick = () => {}
....

onClickonClick={this.handleClick}