最近在写Reactjs,今天在写项目代码的过程中遇到了一个bug,记录一下.

由于项目的css修改,就去修改其中的一个React Component.然后奇怪的事情发生了,component里的Render方法被执行了两次。

代码如下 修改前

var Demo = React.createClass({

  displayName: 'Demo',

  getInitialState: function () {
    return {
      values: []
    };
  },

  handleAdd: function () {
    var values = this.state.values;
    values.push('');
    this.setState({
      values: values
    });
  },

  handleReduce: function (i, e) {
    this.setState({
      values: this.state.values.filter(function (v, _i) {
        return i !== _i;
      })
    });
  },

  handleOnBlur: function (i, e) {
    this.setState({
      values: this.state.values.map(function (v, _i) {
        return i === _i ? e.target.value : v;
      })
    });
  },

  render: function () {
    return React.createElement('div', null,
      React.createElement('button', {
        onClick: this.handleAdd
      }, '+'),
      this.state.values.map(function (v, i) {
        return React.createElement('div', null,
          React.createElement('button', {
            onClick: this.handleReduce(this, i)
          }, '-'),
          React.createElement('input', {
            defaultValue: v,
            onBlur: this.handleOnBlur.bind(this, i)
          })
        );
      }, this)
    );
  }

});

修改后

var Demo = React.createClass({

  displayName: 'Demo',

  getInitialState: function () {
    return {
      values: []
    };
  },

  handleAdd: function (e) {
    e.preventDefault();
    var values = this.state.values;
    values.push('');
    this.setState({
      values: values
    });
  },

  handleReduce: function (i, e) {
    e.preventDefault();
    this.setState({
      values: this.state.values.filter(function (v, _i) {
        return i !== _i;
      })
    });
  },

  handleOnBlur: function (i, e) {
    this.setState({
      values: this.state.values.map(function (v, _i) {
        return i === _i ? e.target.value : v;
      })
    });
  },

  render: function () {
    return React.createElement('div', null,
      React.createElement('button', {
        onClick: this.handleAdd
      }, '+'),
      this.state.values.map(function (v, i) {
        return React.createElement('div', null,
          React.createElement('button', {
            onClick: this.handleReduce(this, i)
          }, '-'),
          React.createElement('input', {
            defaultValue: v,
            onBlur: this.handleOnBlur.bind(this, i)
          })
        );
      }, this)
    );
  }

});

我只是将 div 改成了 label,引起了一个bug,render里的方法被调用了两次。最后调试很久才发现问题出在label这个标签。
HTML里label focus 的话里面的元素也会focus,造成了事件冒泡。当我点击 - 的时候 - button 的事件执行结束以后,传递给 +,结果导致我删除一个输入框以后又回多出一个空白的输入框。 导致一个非常奇怪的bug。
最后的解决办法是在 - 事件执行的最开始添加 e.preventDefault() 函数阻止事件继续传递下去。

这让我想到了之前看到的一句话,在任何事件的执行前都要执行 preventDefault 函数