我们需要在constructor中对于事件与对应的handler函数进行绑定.
大多数时候我们在发出DOM事件的组件内部写我们的handler函数. 在下面的例子中,我们在组件内部创建了一个click handler, 因为我们想所有的Swithcer Component当被点击时,做出同样的响应.
class Switcher extends React.Component {
render() {
return (
<button onClick={ this._handleButtonClick }>
click me
</button>
);
}
_handleButtonClick() {
console.log('Button is clicked');
}
}
上面这样做完全没有问题,因为_handleButtonClick
是一个函数, 我们把这个函数和onClick这个React支持的event绑定在了一起.
但是上面这样做也会带来问题, 使用function的写法, 会在function初始化时生成一个this. 比如我们在_handleButtonClick
里面使用this
, 此时的this是_handleButtonClick
生成出来的, 和Switcher这个class的this没有任何关系, 如果我想访问类似于this.props 或者 this.state这样的对象, 代码便会报错.
class Switcher extends React.Component {
constructor(props) {
super(props);
this.state = { name: 'React in patterns' };
}
render() {
return (
<button onClick={ this._handleButtonClick }>
click me
</button>
);
}
_handleButtonClick() {
console.log(`Button is clicked inside ${ this.state.name }`);
// 将导致
// Uncaught TypeError: Cannot read property 'state' of null
}
}
所以我们常用的解决办法像下面一样使用bind
<button onClick={ this._handleButtonClick.bind(this) }>
click me
</button>
然而, 这种写法意味这我们要一次又一次的去调bind函数, 因为我们的button可能会被渲染很多次. 一种更好的做法是在组件的constructor中去做我们bind函数的调用.
class Switcher extends React.Component {
constructor(props) {
super(props);
this.state = { name: 'React in patterns' };
this._buttonClick = this._handleButtonClick.bind(this);
}
render() {
return (
<button onClick={ this._buttonClick }>
click me
</button>
);
}
_handleButtonClick() {
console.log(`Button is clicked inside ${ this.state.name }`);
}
}
另一种办法是使用箭头函数建立我们的handler函数, 因为箭头函数并不会创建this
.
顺带一提的是, Facebook也推荐使用这种方法去处理需要访问组件的this
的函数.
但是, 在constructor中去做binding也同样有用处. 比如, 我们可能会将父组件中定义的函数作为Props传下去. 因此在子组件中, 我们需要对这个函数进行bind.