揭秘React Class组件的三个小细节
问题一:为啥要用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还是箭头函数都会新创建一个函数,这会可能会破坏它本身严格比较的优化
相比较于这两种,更推荐使用下面两种用法
1、
this.handleClick = this.handleClick.bind(this)
.....
onClick={this.handleClick}
2、
handleClick = () => {}
....
onClickonClick={this.handleClick}