【译】展现型组件和容器型组件(做者:Dan Abramov,Redux的开发者)

本文译自Presentational and Container Components,文章的做者是Dan Abramov,他同时也是Redux和Create React App的做者。 在实际使用React + Redux 技术栈的开发过程当中,很是好的理解了容器型组件和展现型组件的概念是开发出易维护,可复用React App的基础html

在开发React应用的时候,我发现了一种极其简单的开发模式。若是你已经用过一段时间的React,你也许已经发现了它。这篇文章已经讲的很好了,可是我想补充几点。react

若是你将组件分为两类,你会发现它们更容易被复用和理解。我把这两类称为容器型组件展现型组件 ,可是我也据说过其余名字,好比臃肿型组件简单型组件智能型组件傻瓜型组件有状态组件纯组件封装型组件元组件等等。它们不彻底相同,可是在核心观点上是类似的。git

展现型组件github

  • 关心数据的展现方式
  • 内部可能包含展现型组件和容器型组件,而且一般存在其余DOM元素及其样式
  • 容许经过this.props.children控制组件
  • 不依赖app中的其它文件,像Flux的actions或stores
  • 不关心数据是如何加载和变化的
  • 仅经过props接收数据和回调函数
  • 几乎不用组件内的state(若是用到的话,也仅仅是维护UI状态而不是数据状态)
  • 除非须要用到state,生命周期函数或性能优化,一般写成函数式组件
  • 例如:Page,Sidebar,Story,UserInfo,List

容器型组件web

  • 关心数据的运做方式
  • 内部可能包含展现型组件和容器型组件,可是一般没有任何用于自身的DOM元素,除了一些用于包裹元素的div标签,而且不存在样式
  • 为展现型组件和容器型组件提供数据和操做数据的方法
  • 调用Flux actions并以回调函数的方式给展现型组件提供actions
  • 一般是有状态的,而且做为数据源存在
  • 一般由高阶函数生成例如React Redux的connect(),Realy的createContainer,或者Flux Utils的Container.create(),而不是手写的
  • 例如:UserPage,FollowersSidebar,StoryContainer,FollowedUserList

为了清晰的区分这两种组件,我把放在不一样的文件夹中redux

这种方法的优点

  • 关注点分离。经过用这种方式开发组件,你能够更好的理解你的app和UI
  • 更好的复用性。你能够在不一样的数据源中使用相同的展现型组件,也能够把它们放进不一样容器型组件中更进一步的进行复用
  • 展现型组件是你的app必不可少的"调色板",你能够把它们放在一个独立的页面中,让设计师随意拖拽它们的变量而不改变应用的逻辑。在这个页面上进行页面快照回归测试
  • 这种方法逼你去把用于布局的组件抽出来,例如SidebarPageContextMenu。而后经过子组件的方式引入而不是在各个容器型组件中复制粘贴已有的样式和布局

记住,组件不必定要输出DOM元素,它们只须要提供UI之间的组合关系和分界数组

好好利用这一点性能优化

何时引入容器?

我建议你先用展现型组件搭建你的app。最终你会意识到你给中间的组件传递了太多的props。有些组件并不使用这些props,而仅仅向下传递。而且当下层组件须要更多数据的时候,你必须重写改写全部的中间组件。这时候就须要引入一些容器型组件。经过这种方式,你能够从叶子节点组件获取数据和方法,而不用考虑处于中间的组件。app

这须要边开发边重构,因此没有必要一次作对。随着平常应用这种模式,你会组件培养出一种『这时候我该抽出一个Container』的直接,就像你已经知道何时应该提取出一个函数同样。个人Redux教程可能也会帮你一把less

其余的二分法

展现型组件和容器型组件这种分类并不是十分严格,这是按照它们的目的进行分类。

为了与以前的概念作比较,这是一些相关但不一样的二分法

  • 有状态和无状态 有些组件使用React的setState()方法,有些不用。容器型组件每每是有状态的而展现型组件每每是无状态的,这并非一条铁律。展现型组件也能够是有状态的,容器型组件也能够是无状态的
  • 类和函数 从React0.14开始,组件既能够声明为类也能够声明为函数。函数式组件能够定义的更简单可是也缺乏一些只能在类组件中使用的特写。有些限制可能将来会消除,可是在当下仍然是存在的。因为函数式组件更加易于理解,因此我建议你尽可能的使用它。除非你须要state,生命周期函数,或者性能优化,这些特性只有在类组件中才可使用。
  • 纯和非纯 若是一个组件在输入相同props的状况下老是输出相同的结果,那咱们称这个组件为pure component。pure component既能够声明为类组件也能够声明为函数式组件,便可以是有状态的也能够是无状态的。另外一个重要的方面是,pure component不依赖propsstate的深层比对,因此能够在shouldComponentUpdate方法中进行浅比较优化性能,可是在将来可能有不少变化。

展现型组件和容器型组件均可以放进以上任何一种二分法中。在我看来,展现型组件每每是无状态的纯函数组件,容器型组件每每是有状态的纯类组件。然而这并非一种要求,而是一种现象,而且在一些特定的场景中我也确实见过彻底相反的状况。

不要把展现型组件和容器型组件的划分当成教条。有的时候没有必要对两者进行区分。若是你不太肯定一个组件是展现型组件仍是容器型组件,也许如今还不是区分它的时候,别太心急!

例子

Michael Chan为咱们用一个gist阐释了上面的道理

延伸阅读

相关文章
相关标签/搜索