内容简介:如果你最近有在做React 开发,你肯定有遇到像 HOCs 和 Render Props 这样的术语。在本文中,我们将深入探讨这两种模式,以便了解我们为什么需要它们,以及如何正确地使用它们来构建更好的 React 应用。React 提供了一种简单的代码复用方式,即
如果你最近有在做React 开发,你肯定有遇到像 HOCs 和 Render Props 这样的术语。在本文中,我们将深入探讨这两种模式,以便了解我们为什么需要它们,以及如何正确地使用它们来构建更好的 React 应用。
为什么我们需要这些模式?
React 提供了一种简单的代码复用方式,即 组件 。组件封装了很多东西,包括内容、样式和业务逻辑。理想情况下,在单个组件中,我们可以将 html、css 和 js 结合起来,所有的这些是为了一个目的,单一职责。
提示:使用 Bit (Github) ,你可以组织和分享 可复用的组件 ,这些组件可以从不同的项目和应用中被发现,分享和开发。这比重写组件或者维护一个大型库要快得多。试试看 :)
例子
假设我们正在开发一个电子商务应用程序。它与其他电子商务应用程序一样,向用户显示所有可购买产品,并且用户可以将任何产品添加到购物车。我们将从 API 获取产品数据,并将产品目录显示为卡片列表。
在这种情况下,React 组件可以像这样实现:
对于我们的管理员,有一个管理门户,他们可以在其中添加或删除产品。在此门户中,我们从同一 API 获取产品数据,并以表格形式显示产品目录。
这个 React 组件可以像这样实现:
有一件事很明显,这两个组件都实现了产品的数据获取逻辑。
继续深入,以下这些情况也可能出现:
ProductList
如果我们为这些每一点都写个不同的组件,那么我们将要复制大量的代码。
获取数据和显示数据是两个独立的关注点。正如前面所说的,如果一个组件有一个责任会更好。
让我们重构第一个组件。它将接受产品数据为属性,并像之前一样把产品目录渲染成卡片列表。由于我们不需要 组件状态和生命周期方法 ,我们把它转换成函数式组件。
它现在看起来是这样的:
ProductList.js (代码链接)
就像 ProductList
和 ProductTable
会是一个函数组件,它接收产品数据为属性,并把数据渲染到表的行中去。
现在让我们创建一个名为 ProductsData
的组件。它从 API 获取产品数据。数据的获取和状态的更新将和原先的 ProductList
组件一样。但是我们应该在这个组件的 render 方法中放入什么呢?
ProductData.js (代码链接)
如果我们只是简单的放入 ProductList 组件,那么我们就不能复用这个组件于 ProductTable。不管怎样,如果这个组件可以询问要渲染什么,那个问题就会得到解决。在一个地方,我们将告诉它要渲染 ProductList
组件,而在管理门户中,我们告诉它要渲染 ProductTable
组件。
这就是 Render Props 和 HOCs 发挥作用的地方。它们只是一类方法,即对于一个组件,会询问应该渲染什么内容。这进一步推动了代码的复用。
现在我们知道了为什么需要它们,让我们来看看如何使用它们。
Render Props
在概念层面理解 Render Props 非常简单。让我们忘掉 React 一会,然后看看原生 JavaScript 下的事情。
我们有一个计算两个数字之和的函数。起初我们只想要把结果记录到控制台。所以,我们这样设计函数:
但是,我们很快发现 sum 函数非常有用,我们需要在其他地方使用到它。因此,我们希望 sum 函数只提供结果,而不是将其记录到控制台,并让调用者决定如何使用结果。
它可以这么做:
我们传给 sum
函数一个 fn
回调函数作为参数。然后 sum
函数计算结果并把结果作为参数调用 fn
。通过这种方式,回调函数可以获得结果,并且可以自由地对结果进行任何操作。
这就是 Render Props 的本质。我们将通过使用这个模式来更清晰地认识它,所以让我们立刻把它用到我们现在面临的问题中去吧。
在这不是计算两个数字之和的函数,而是获取产品数据的组件 ProductsData
。现在可以通过属性传递给 ProductsData
组件一个函数。然后 ProductsData
组件将获取产品数据,并将这些数据提供给以属性方式传递进来的函数。传递进来的函数现在可以对产品数据做任何它想做的事情。
在 React 中,它可以像这样实现:
就像 fn
参数,我们有一个 render 属性,它将作为一个函数被传递。然后 ProductData
组件把产品数据作为参数调用这个函数。
因此我们可以以这种方式使用 ProductData
组件。
正如我们所看到的 Render Props 是一种相当通用的模式。大部分事情都可以非常直接地完成。但这也是我们搬起石头砸自己的脚的原因:
避免嵌套的一种简单方法是把组件拆解成更小的组件,并将这些组件保存在单独的文件中。另一种方法是编写更多的组件并组合它们,而不是在 Render Props 中使用长函数。
接下来,我们将看下另一种流行的模式,它被称为 HOC。
高阶组件(HOC)
在这个模式中,我们定义了一个函数,该函数接受一个组件作为参数,然后返回相同的组件,但是添加了一些功能。
如果这听起来很熟悉,那是因为它类似于 Mobx 中广泛使用的装饰器模式。像 Python 这样的许多语言都内置了装饰器,JavaScript也很快就会支持装饰器。HOCs 很像装饰器。
比起用文字解释,用通过代码来理解 HOCs 会容易很多。所以让我们先来看代码。
正如我们所看到的,数据获取和状态更新逻辑就和我们在 Render Props 所做的一样。唯一的变化就是组件类是位于函数内部。该函数接受一个组件为参数,然后在内部的 render 方法中渲染这个组件,但是会添加额外的属性。对于名称如此复杂的模式,实现起来相当简单,对吧?
现在我们已经了解了为什么我们需要 Render Props,HOCs 以及我们如何实现它们。
还有一个问题:如何在 Render Props 和 HOCs 中进行选择?关于这个话题的文章已经有很多了,所以我现在不讨论这个话题。也许在我的下一篇文章中 :)
什么时候不要使用 Render Props — Kent C. Dodds
HOCs vs Render Props — Richard Kotze
以上所述就是小编给大家介绍的《[译] 理解 React Render Props 和 HOC》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 理解原型其实是理解原型链
- 要理解深度学习,必须突破常规视角去理解优化
- 深入理解java虚拟机(1) -- 理解HotSpot内存区域
- 荐 【C++100问】深入理解理解顶层const和底层const
- 深入理解 HTTPS
- 深入理解 HTTPS
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。