• 事件处理

    事件处理

    我们需要在constructor中对于事件与对应的handler函数进行绑定.

    大多数时候我们在发出DOM事件的组件内部写我们的handler函数.
    在下面的例子中,我们在组件内部创建了一个click handler, 因为我们想所有的Swithcer Component当被点击时,做出同样的响应.

    1. class Switcher extends React.Component {
    2. render() {
    3. return (
    4. <button onClick={ this._handleButtonClick }>
    5. click me
    6. </button>
    7. );
    8. }
    9. _handleButtonClick() {
    10. console.log('Button is clicked');
    11. }
    12. }

    上面这样做完全没有问题,因为_handleButtonClick是一个函数, 我们把这个函数和onClick这个React支持的event绑定在了一起.

    但是上面这样做也会带来问题, 使用function的写法, 会在function初始化时生成一个this. 比如我们在_handleButtonClick里面使用this, 此时的this是_handleButtonClick生成出来的, 和Switcher这个class的this没有任何关系, 如果我想访问类似于this.props 或者 this.state这样的对象, 代码便会报错.

    1. class Switcher extends React.Component {
    2. constructor(props) {
    3. super(props);
    4. this.state = { name: 'React in patterns' };
    5. }
    6. render() {
    7. return (
    8. <button onClick={ this._handleButtonClick }>
    9. click me
    10. </button>
    11. );
    12. }
    13. _handleButtonClick() {
    14. console.log(`Button is clicked inside ${ this.state.name }`);
    15. // 将导致
    16. // Uncaught TypeError: Cannot read property 'state' of null
    17. }
    18. }

    所以我们常用的解决办法像下面一样使用bind

    1. <button onClick={ this._handleButtonClick.bind(this) }>
    2. click me
    3. </button>

    然而, 这种写法意味这我们要一次又一次的去调bind函数, 因为我们的button可能会被渲染很多次.
    一种更好的做法是在组件的constructor中去做我们bind函数的调用.

    1. class Switcher extends React.Component {
    2. constructor(props) {
    3. super(props);
    4. this.state = { name: 'React in patterns' };
    5. this._buttonClick = this._handleButtonClick.bind(this);
    6. }
    7. render() {
    8. return (
    9. <button onClick={ this._buttonClick }>
    10. click me
    11. </button>
    12. );
    13. }
    14. _handleButtonClick() {
    15. console.log(`Button is clicked inside ${ this.state.name }`);
    16. }
    17. }

    另一种办法是使用箭头函数建立我们的handler函数, 因为箭头函数并不会创建this.

    顺带一提的是, Facebook也推荐使用这种方法去处理需要访问组件的this的函数.

    但是, 在constructor中去做binding也同样有用处. 比如, 我们可能会将父组件中定义的函数作为Props传下去. 因此在子组件中, 我们需要对这个函数进行bind.