组件规范

为了减少编码过程中可能出现的问题,我们制定了如下规范,希望能减少常见的错误。

  • 有状态组件只有 render 方法才能返回 JSX,因为 JSX 中的虚拟 DOM 有一个 _owner 属性,这与它与组件实例进行绑定。如果其他方法里使用了 JSX, _owner 就没有与组件实例进行绑定。

  • render 方法里面应该以 < 开头,不应该存在 if else 分支,视情况返回不同的JSX。相同的组件应该返回相同的顶级元素容器。

// 不好的实践
render() {
   if (this.state.a) {
      return <strong>不要</strong>
   } else {
      return <div>这样</div>
   }
}
  • ref 应该尽快淘汰字符串形式,因为字符串形式的 ref 会自始至终将字符串放在 refs 对象中,会有泄露的问题。
// 不好的实践
<Foo
  ref="myRef"
/>

// 一般的实践
<Foo
  ref={(ref) => { this.myRef = ref; }}
/>

上面的方法之所以是一般的实践,而不是好的实践,是因为我们在查看组件时,别人很难察觉到你在 JSX 里偷偷为组件添加了一个新属性。组件所有用到的属性,应该都能在 constructordefaultProps 中找到。

  • refs.xxx 中的 DOM 节点,不应该再转存到组件实例上或其他地方中。每次访问 refs.xxx 必须判定其是否为空。

  • 不要在 componentWillUpdate/componentDidUpdate/render 中执行 setState, 可能导致死循环。

  • 不要在 JSX 中使用 bind 方法绑定组件实例

// 不好的实践
class extends React.Component {
  onClickDiv() {
    // do something
  }

  render() {
    return <div onClick={this.onClickDiv.bind(this)} />;
  }
}

// 好的实践
class extends React.Component {
  constructor(props) {
    super(props);

    this.onClickDiv = this.onClickDiv.bind(this);
  }

  onClickDiv() {
    // do something
  }

  render() {
    return <div onClick={this.onClickDiv} />;
  }
}
  • 不要使用 cloneElement, createElement, 让 JSX 与 babel 帮你创建它们。

  • 不要使用 createClass, mixin, PropTypes(它们已经被移出核心库,被逐渐边缘化,有关属性的描述改成文档注释吧)。