[note: 本文基于 React v15.3.0+ 进行讨论]html
通常来讲,编写 React 组件的方式有如下三种:react
PureComponent
的组件;Component
的组件,这也是最常使用的组件形式。那么,这三种形式的使用场景及优劣各是什么呢?git
无状态组件是经过函数定义的,好比下面这个最简单的?:github
let Hello = (props) => <div>Hello {props.name}</div>
调用的时候,和日常组件的使用方式相同:redux
<Hello name="cjf" />
能够看出,无状态组件的最大特征就是没有内部状态(废话),因此无状态组件的渲染结果彻底取决于输入的 props
。数组
无状态组件的优势有如下几个方面:less
缺点有如下两点:函数
props
,它就会进行从新渲染。固然还有一点须要注意的是,无状态组件对于 props
是浅比较的。PureComponent
的组件这类组件的定义方式以下:post
class MyComponent extends PureComponent {...}
PureComponent
是继承于 Component
类的,不一样的是内部实现了 shouldComponentUpdate
的优化。它会浅比较组件内部 props
和 state
的值,从而决定组件应不该该从新渲染,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()
就是容器组件的一种具体实现。