React 组件的三种形式

[note: 本文基于 React v15.3.0+ 进行讨论]html

通常来讲,编写 React 组件的方式有如下三种:react

  1. 无状态组件(stateless component)。它是函数式的,不继承于任何类;
  2. 继承于 PureComponent 的组件;
  3. 继承于 Component 的组件,这也是最常使用的组件形式。

那么,这三种形式的使用场景及优劣各是什么呢?git

无状态组件

无状态组件是经过函数定义的,好比下面这个最简单的?:github

let Hello = (props) => <div>Hello {props.name}</div>

调用的时候,和日常组件的使用方式相同:redux

<Hello name="cjf" />

能够看出,无状态组件的最大特征就是没有内部状态(废话),因此无状态组件的渲染结果彻底取决于输入的 props数组

无状态组件的优势有如下几个方面:less

  • 简单;
  • 可复用性高。由于无状态组件不包含内部状态,也就是没有内在逻辑,输出彻底取决于输入,因此复用组件只须要输入不一样的数据便可;
  • 单元测试更容易进行。由于逻辑都被移出了 view 层,因此单元测试时不须要渲染任何东西,能够专一于单个逻辑。

缺点有如下两点:函数

  • 无状态组件中不能使用生命周期函数。若是必定要用的话,只能在外面包一层父组件,而后定义生命周期函数;
  • 没法手动控制无状态组件的从新渲染(re-render)。只要无状态组件接收到了新的 props,它就会进行从新渲染。固然还有一点须要注意的是,无状态组件对于 props 是浅比较的。

继承于 PureComponent 的组件

这类组件的定义方式以下:post

class MyComponent extends PureComponent {...}

PureComponent 是继承于 Component 类的,不一样的是内部实现了 shouldComponentUpdate 的优化。它会浅比较组件内部 propsstate 的值,从而决定组件应不该该从新渲染,PureComponent 的使用能够提升 React 应用的性能。性能

PureComponent 中,咱们不须要写相似于

if (this.state.someVal !== computedVal) {
  this.setState({ someVal: computedVal })
}

的代码来避免组件被重复渲染。

让咱们看看源码
当一个组件是 PureComponent 时,会执行下面操做来检查是否须要 update

if (type.prototype && type.prototype.isPureReactComponent) {
  return (
    !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState)
  );
}

这里用的也是浅比较(shallowEqual),因此对于多层嵌套的对象和数组中的变化都不会被检测到。好比下面这个例子:

handleClick() {
  let { items } = this.state

  items.push('new-item')
  this.setState({ items })
}

render() {
  return (
    <div>
      <button onClick={::this.handleClick} />
      <ItemList items={ this.state.items } />
    </div>
  )
}

假设 ItemList 是一个 PureComponent,由于它执行的是浅比较,因此 this.state.items 的变化是不会触发 ItemList 的更新的。若是要触发更新,应该使用 setState 的另外一种调用形式,每次都返回一个新的对象:

handleClick() {
  this.setState(prevState => ({
    words: prevState.items.concat(['new-item'])
  }));
}

最后须要注意的是,在 PureComponent 中是不能本身定义的 shouldComponentUpdate() 方法的。若是实在有这个必要,只能使用 Component 组件。

继承于 Component 的组件

没啥说的,这就是最普通的组件形式。

后续

从上面的讨论咱们能够得出结论,在 React 应用中,应当尽量多的使用无状态组件或 PureComponent 以加强复用性和提升性能。可是,在具体的项目实践中,咱们每每须要经过 Ajax 请求获取数据,并进一步对数据进行处理。为了使组件的职责更加单一,引入了容器组件(Container Component)的概念。咱们能够将数据获取以及处理的逻辑放在容器组件中,而后将已处理的数据传递给展现组件,使得组件的耦合性进一步地下降。

react-redux 中的 connect() 就是容器组件的一种具体实现。

参考文献:

  1. https://stackoverflow.com/que...
  2. https://facebook.github.io/re...
  3. https://github.com/eyasliu/bl...
  4. https://juejin.im/post/596d65...
  5. http://www.zcfy.cc/article/re...
  6. https://60devs.com/pure-compo...
  7. http://www.jianshu.com/p/980a...
相关文章
相关标签/搜索