在react中,在组件事件上绑定this通常有三种写法
-
inline function
<Button onClick={() => this.handleChange></Button>
-
class properties
class A {
handleChange = () => {
coneole.log()
}
}
-
bind
class B {
constructor() {
this.handleChange = this.handleChange.bind(this)
}
handleChange() {
console.log()
}
}
哪种方法相较而言更适合呢,这个在React的Github Issue里都已经有过多次讨论。react/react#9851 根据Dan Abramov的说法,两者基本一致,但在Facebook内部使用的是第二种方法(calss properties)。
虽然两者基本一致,但是肯定有细微的差别,第二种方法因为目前还不是ES的正式语法,所有需要使用babel插件babel-plugin-transform-class-properties进行转义,下面是babel转换A和B的代码
var A = function A() {
_classCallCheck(this, A);
this.handleChange = function () {
coneole.log();
};
};
var B = function () {
function B() {
_classCallCheck(this, B);
this.handleChange = this.handleChange.bind(this);
}
_createClass(B, [{
key: "handleChange",
value: function handleChange() {
console.log();
}
}]);
return B;
}();
我们在这里分别实例化上面代码中的A和B并打印这两个实例,如下图

使用class properties语法的A实例handleChange只存在实例上,使用bind绑定this的在实例和原型上分别存在handleChange方法, 看上去似乎前者的开销比后者小。
性能方面,可以做个测试进行对比,https://jsperf.com/arrow-function-vs-bound-function-with-100-instances。

op/s的测试结果显示bind方式比class properties在性能方面更加优秀,但是没有超过50%,优势不是很大。
但是如果如果在constructor中显式bind this,那么在组件中如果含有大量事件,是会拖慢组件初始化速度,是你的应用程序变慢。
有一种说法是如果你的组件性能受到的影响微乎其微,不要过早的进行优化,因为可能带来副作用,只有在观测到时在进行优化。
第一种内联函数方式是最不被人接受的,因为垃圾回收机制和在使用pureComponent ,在组件中内联的使用一个对象会使Shallow Compare 失效,因为总会产生一个新的对象,是严格不相等的,从而引起重新渲染。
但是有中情况是需要从外部传递参数给事件函数,这种情况下我们不得不使用内联函数,有一种解决方案是讲数据传递到html的表单元素上,通过e.target.value获取。
class C {
handleClick = (e) => {
const id = e.target.value
// do something
}
render() {
const id = {this.state}
return (<button value={id} onClick={this.handleClick}>提交</button>)
}
}
还有一种解决方案是提取子组件,具体可以看这篇文章https://medium.freecodecamp.org/react-pattern-extract-child-components-to-avoid-binding-e3ad8310725e 但两者都有相应局限性,不是广泛的适用于所有场景。
如果你的组件不是追求极限性能优化或者是拥有超多的子组件,不论采用2和3哪种方式,都是可以的,主要还是看团队规范。
在react中,在组件事件上绑定this通常有三种写法
inline function
class properties
bind
哪种方法相较而言更适合呢,这个在React的Github Issue里都已经有过多次讨论。react/react#9851 根据Dan Abramov的说法,两者基本一致,但在Facebook内部使用的是第二种方法(calss properties)。
虽然两者基本一致,但是肯定有细微的差别,第二种方法因为目前还不是ES的正式语法,所有需要使用babel插件
babel-plugin-transform-class-properties进行转义,下面是babel转换A和B的代码我们在这里分别实例化上面代码中的A和B并打印这两个实例,如下图

使用class properties语法的A实例handleChange只存在实例上,使用bind绑定this的在实例和原型上分别存在handleChange方法, 看上去似乎前者的开销比后者小。
性能方面,可以做个测试进行对比,https://jsperf.com/arrow-function-vs-bound-function-with-100-instances。
op/s的测试结果显示bind方式比class properties在性能方面更加优秀,但是没有超过50%,优势不是很大。
但是如果如果在constructor中显式bind this,那么在组件中如果含有大量事件,是会拖慢组件初始化速度,是你的应用程序变慢。
有一种说法是如果你的组件性能受到的影响微乎其微,不要过早的进行优化,因为可能带来副作用,只有在观测到时在进行优化。
第一种内联函数方式是最不被人接受的,因为垃圾回收机制和在使用pureComponent ,在组件中内联的使用一个对象会使Shallow Compare 失效,因为总会产生一个新的对象,是严格不相等的,从而引起重新渲染。
但是有中情况是需要从外部传递参数给事件函数,这种情况下我们不得不使用内联函数,有一种解决方案是讲数据传递到html的表单元素上,通过e.target.value获取。
还有一种解决方案是提取子组件,具体可以看这篇文章https://medium.freecodecamp.org/react-pattern-extract-child-components-to-avoid-binding-e3ad8310725e 但两者都有相应局限性,不是广泛的适用于所有场景。
如果你的组件不是追求极限性能优化或者是拥有超多的子组件,不论采用2和3哪种方式,都是可以的,主要还是看团队规范。