react 组件设计模式

react component 模式

有状态组件(Stateful)和无状态组件(Stateless)、容器组件(Container)与展示组件(Presentational)、高阶组件(HOC)、渲染回调(Render Callbacks)等

我在工作中使用 React 有一段时间了——一个 facebook 使用 js 渲染用户界面的框架——刚开始的时候我想知道一些概念。这些文字是尝试总结我实践这么久以来学到的一些模式——可能对于刚开始进入组件世界的开发者有用。

有状态(Stateful) 与 无状态(Stateless) 组件

就像有状态和无状态的 web 服务一样, React 组件也能在用户使用时保存和操作状态(有状态)。或只是一个简单的组件,按受 props 并返回需要显示的内容(无状态)。

一个简单的 无状态 按钮组件只接受 props:

https://cdn-images-1.medium.com/max/1600/1*fgZOSwpdU7MMNxltRcXAcQ.png

而下面是一个 有状态 的计数组件(使用了 Button 组件):

https://cdn-images-1.medium.com/max/1600/1*TYPgsZUZMoo7lW7xv4gxYw.png

就像你所看到的,最后一个组件的 constructor 保持了一个组件的 state, 而第一个组件则是一个简单组件,只通过 props 渲染了文字。这个关注分离可能非常简单,但是让 Button 组件高度复用。

容器(Container) 与 展示(Presentational) 组件

当使用外部数据运行时,我们可以把这个组件分成这两个新类别。容器组件 负责获取数据,存在在 react 作用域外部,就像连接 ReduxRelay ———— 而 展示组件 则不依赖 react 应用的其他部分,仅仅取决于它自身的 state 和接收的 props。让我们拿用户列表作为展示组件的例子:

https://cdn-images-1.medium.com/max/1600/1*wbih6jbxJiIgNOXgRpcROA.png

这个列表可以使用我们的 容器组件 更新:

https://cdn-images-1.medium.com/max/1600/1*TJxCVhawM2e99dZsxu11oA.png

这种方法将数据获取与渲染分离,同时让 UserList 高度复用。如果你想进一步学习这种模式,这里有一篇文章解释地很好。

高阶组件

高阶组件————或叫 HOC。当你想要重用逻辑的时候非常感兴趣。他们是 javascript 函数,将一个组件作为参数,并返回新组件。

假设你需要做一个可伸缩的的菜单组件,当用户点的时候,展示它里面的内容。所以,为了替代在父级组件上控制 state,你可以简单地创建一个通用的 高阶组件 来处理它:

https://cdn-images-1.medium.com/max/1600/1*qchJXtrHlR46phKFDDJeeQ.png

这种方式允许我们将逻辑应用通过装饰模式(decorator)应用在 ToggleableMenu 组件上。

https://cdn-images-1.medium.com/max/1600/1*RQuGzKKbT7R9OIDBzhO8gg.png

现在我们可以任意传递子级到 ToggleableMenu 组件了:

https://cdn-images-1.medium.com/max/1600/1*rWCZQqL0Rbizbrw_yjgxgA.png

如果你熟悉使用 reduxconnect 或 react router 的 withRouter 函数,那你已经在用 HOCs 了。

渲染回调(Render Callbacks)

另一种让组件逻辑复用的很棒的方法是 将组件子级转换成函数。这也是为什么 渲染回调(Render Callbacks) 也叫作 Function as Child Components。我们可以拿可伸展的菜单高阶组件作为例子,并使用 渲染回调 重写它。

https://cdn-images-1.medium.com/max/1600/1*Ul-ubPnaOFtY4mTeM5PW3A.png

现在我们可以传递一个函数作为 Toggleable 的子组件:

https://cdn-images-1.medium.com/max/1600/1*cwoZiIT3Gcau5lDwyCQzQw.png

上面的代码已经使用函数作为子级,但,如果我们想要像高阶组件的例子那样复用它(多个菜单),我们可以简单地使用 Toggleable 逻辑创建一个新组件:

https://cdn-images-1.medium.com/max/1600/1*DVfPDwHw_eH9dUeX9w5GEg.png

我们的新产品 ToggleableMenu 组件已经准备好了:

https://cdn-images-1.medium.com/max/1600/1*hzpuJMAMTRQZK_vKCK_jhQ.png

这种方式真的非常有用,当我们需要更改渲染内容而不用管 state 操作时:就像你所看到的,我们可以将渲染逻辑移动到 ToggleableMenu 的子级函数中,但却保持我们 Toggleable 组件的 state 逻辑!

进一步阅读

上面的例子只是一些可以用在 react 编程中的基础模式,如果你真的想深入这个主题,我建议你看看这些了不起的文章:

0%