React中的演示(UI)组件和容器组件
Hancoson opened this issue · 0 comments
在React
中的组件可以分为presentational components
即UI(演示)组件和container components
即容器组件。今天就来说说他们两个的区别以及这样的好处。
区别
我的演示组件:
- 它只关心事物的样子。
- 内部可以包含容器组件,通常有一些自己的DOM标记和样式。
- 通常可以通过
this.props.children
进行控制。 - 对应用程序的其余部分没有依赖关系,例如
Flux
的action
和stores
。 - 不需要指定数据的加载或变异。
- 通过
props
接受和会掉数据。 - 很少有自己的状态。
- 被编写为功能组件,除非它们需要状态,生命周期或性能优化。
- 示例:页面,边栏,故事,用户信息,列表。
我的容器组件:
- 关心事情如何运作
- 可能包含容器组件,但通常没有自己的任何DOM标记,除了一些包装div,并且没有任何样式。
- 向演示组件或其他容器组件提供数据和行为。
- 调用
Flux/redux
操作,并将其作为回调给演示组件。 - 通常是有状态的,因为它们往往作为数据源。
- 通常使用更高阶的组件(如来自
Reat
Redux
的connect()
),来自Relay
的createContainer()
或来自Flux
Utils
的Container.create()
生成的,而不是用手写。 - 示例:UserPage,FollowersSidebar,StoryContainer,FollowedUserList。
好处
- 更好的分离问题。通过以这种方式编写组件,您可以更好地理解您的应用程序和UI。
- 更好的可重用性。您可以使用完全不同的状态源的相同的演示组件,并将其转换为可以进一步重复使用的单独的容器组件。
- 演示组件本质上是您的应用程序的“调色板”。您可以将它们放在一个页面上,让设计师调整所有的变体,而不用触摸应用程序的逻辑。您可以在该页面上运行截图回归测试。
- 这迫使您提取“布局组件”,例如Sidebar,Page,ContextMenu,并使用
this.props.children
,而不是在多个容器组件中复制相同的标记和布局。
记住,组件不必发出DOM。他们只需要在UI问题之间提供组合界限。
何时使用容器组件
我建议您开始构建您的应用程序的时候从UI组件开始。最终你会意识到,你正在把太多的props
传给中间组件。当您注意到某些组件不使用他们收到的props
,而只是转发它们,并且您必须在子组件需要更多数据时重新连接所有这些中间组件,这是引入一些容器组件的好时机。这样,您可以将数据和props
到子组件,而不需要在不相关组件中负担。
这是一个持续的重构过程,所以不要开始就尝试。当您尝试使用此模式时,您将开始直观的了解何时抽出一些容器,就像您知道何时提取功能一样。
其他方法
重要的是,您明白UI组件和容器之间的区别不是一个技术性的。相反,它的目的是区别的。
相比之下,这里有一些相关(但不同的)技术区别:
- 有状态和无状态的。一些组件使用
React
setState()
方法,有些则不使用。虽然容器组件往往是有状态的,而且表示组件往往是无状态的,但这并不是一个难题。演示组件可以是有状态的,容器也可以是无状态的。 - 类和函数。由于
React 0.14
,组件可以被声明为类和函数。功能组件更容易定义,但它们缺少当前仅适用于类组件的某些功能。其中一些限制可能会在将来消失,但今天存在。由于功能组件更易于理解,我建议您使用它们,除非您需要状态,生命周期或性能优化,这些类型组件此时才可用。 - 纯净和不纯。人们说如果一个组件是纯粹的,如果它保证返回相同的结果给予相同的道具和状态。纯组件可以被定义为类和函数,并且可以是有状态的和无状态的。纯组件的另一个重要方面是它们不依赖于道具或状态中的深层突变,因此它们的渲染性能可以通过其
shouldComponentUpdate()
钩子中的浅层比较来优化。目前只有类可以定义shouldComponentUpdate()
,但可能会在将来发生更改。
两个UI组件和容器都可以落入这些存储桶中。根据我的经验,UI组件往往是无状态的纯函数,容器往往是有状态的纯类。然而,这不是一个规则,而是一个观察,我已经看到与具体情况有关的恰恰相反的情况。
不要将UI和容器组件分离作为一个教条。有时候没有关系,也很难绘制线。如果您不确定特定组件是否应该是表示性的还是集装箱的,那么决定可能还为时过早。不要着急!
延伸阅读
Getting Started with Redux
Mixins are Dead, Long Live Composition
Container Components
Atomic Web Design
Building the Facebook News Feed with Relay