高阶组件(HOC)是 React 中一项有趣的技术,用于重构共享几乎相同逻辑的类似组件。我知道这听起来很抽象而且很高级。然而,它是一种并非特定于 React 的架构模式,因此您可以使用该方法来做很多事情。
例如,您可以使用它向某个组件添加加载指示器,而无需调整原始组件,或者您可以隐藏组件的属性以使其不那么冗长。应用程序有很多,我试图在本教程中介绍其中的大部分。
还有其他几个教程可以教您有关 HOC 的知识,但其中大多数都是针对高级 React 开发人员的。当我开始学习 React 时,我很难理解高阶组件的概念以及如何将 HOC 合并到我的项目中以编写更好的代码。本文将解释您需要了解的 HOC 从头到孵化的所有内容。
本教程分为三个部分。第一部分将介绍高阶组件的概念。在这里,我们将讨论在查看高阶函数和 HOC 之前需要了解的语法。第二部分是本系列中最令人兴奋的部分,您将看到 HOC 的实际示例。我们将使用 HOC 来创建表单、授权和许多其他事情。
在本教程的第三部分中,我们将更多地关注最佳实践以及实现高阶组件时需要考虑的事项。我们还将简要介绍 React 中代码共享的替代模式,例如 Render props。
在开始之前,最好先看看有状态组件与无状态组件的教程,以便更好地理解 React 的组件架构。
我们很快就会动手。但在此之前,我认为您应该了解一些事情。我更喜欢尽可能使用 ES6 语法,它与 HOC 配合得很好。作为初学者,HOC 有意义,但某些 ES6 语法却没有意义。因此,我建议您先浏览一遍本节,稍后您可以再回来参考。
箭头函数是常规函数表达式,但语法较短。它们最适合非方法函数,这也是我们特别感兴趣的。以下是一些帮助您入门的示例:
/* Functions without parameters */ function () { return "This is a function expression"; } // is equivalent to () => { return "This is an arrow function expression" } // or () => "Arrow with a shorter syntax"
/* Function with a single parameter */ function (param) { return { title: "This function accepts a parameter and returns an object", params: param} } // is syntax-equivalent to param => { return { title: "This arrow function accepts a single parameter", params: param } }
/* Function with multiple parameters */ function (param1, param2) { return { title: "This function accepts multiple parameters", params: [param1,param2]} } // is syntax-equivalent to (param1, param2) => { return {title: "Arrow function with multiple parameters", params: [param1, param2] } } // or (param1, param2) => ({ title: "Arrow function with multiple parameters", params: [param1, param2] })
虽然这个名字暗示它与流行的印度美食中的一道异国菜肴有关,但事实并非如此。柯里化可帮助您将接受多个参数的函数分解为一系列一次接受一个参数的函数。这是一个例子:
//Usual sum function const sum = (a, b) => a + b //Curried sum function const curriedSum = function (a) { return function (b) { return a+b } //Curried sum function using arrow syntax const curriedSum = a => b => a+b curriedSum(5)(4) //9
该函数只接受一个参数,并返回一个接受另一个参数的函数,这种情况一直持续到满足所有参数为止。
curriedSum // (a) => (b) => a+b curriedSum(4) // (b) => 4+b curriedSum(4)(5) //4+5
一个密切相关的术语称为“部分应用”。部分应用程序通过预先填充现有函数的一些参数来创建新函数。新创建的函数的元数(即参数数量)将小于原始函数的元数。
扩展运算符扩展数组、字符串或对象表达式的内容。以下是您可以使用传播运算符执行的操作的列表
/*Spread Syntax in Function Calls */ const add = (x,y,z) => x+y+z const args = [1,2,3] add(...args) // 6
/* Spread in Array Literals */ const twoAndThree = ['two', 'three']; const numbers = ['one', ...twoAndThree, 'four', 'five']; // ["one", "two", "three", "four", "five"]
/* Spread in Object Literals */ const contactName = { name: { first: "Foo", middle: "Lux", last: "Bar" } } const contactData = { email: "fooluxbar@example.com", phone: "1234567890" } const contact = {...contactName, ...contactData} /* { name: { first: "Foo", middle: "Lux", last: "Bar" } email: "fooluxbar@example.com" phone: "1234567890" } */
我个人喜欢三个点可以让您更轻松地将现有道具传递给子组件或创建新道具的方式。
const ParentComponent = (props) => { const newProps = { foo: 'default' }; return ( <ChildComponent {...props} {...newProps} /> ) }
现在我们已经了解了构建 HOC 的基本 ES6 语法,让我们看看它们是什么。
什么是高阶函数?维基百科有一个简单的定义:
在数学和计算机科学中,高阶函数(也称为泛函、函数形式或函子)是一种接受一个或多个函数作为参数或返回一个函数作为其结果或两者兼而有之的函数。
您之前可能以某种形式在 JavaScript 中使用过高阶函数,因为这就是 JavaScript 的工作方式。将匿名函数或回调作为参数传递或返回另一个函数的函数 - 所有这些都属于高阶函数。下面的代码创建了一个本质上更高阶的计算器函数。
const calculator = (inputFunction) => (...args) => { const resultValue = inputFunction(...args); console.log(resultValue); return resultValue; } const add = (...all) => { return all.reduce( (a,b) => a+b,0) ; } const multiply = (...all) => { return all.reduce((a,b)=> a*b,1); }
让我们更深入地了解一下这一点。 calculator()
接受一个函数作为输入并返回另一个函数——这完全符合我们对高阶函数的定义。因为我们使用了剩余参数语法,所以返回的函数将其所有参数收集在一个数组中。
然后,使用传递的所有参数调用输入函数,并将输出记录到控制台。所以计算器是一个柯里化的高阶函数,你可以像这样使用计算器:
calculator(multiply)(2,4); // returns 8 calculator(add)(3,6,9,12,15,18); // returns 63
插入一个函数,例如 add()
或 multiply()
和任意数量的参数,以及 calculator()
将从那里拿走它。所以计算器是一个扩展了 add()
和 multiply()
功能的容器。它使我们能够在更高或更抽象的层面上处理问题。乍一看,这种方法的好处包括:
现在我们对高阶函数有了一个很好的了解,让我们看看高阶组件的能力。
高阶组件是一个接受组件作为参数并返回该组件的扩展版本的函数。
(InputComponent) => { return ExtendedComponent } // or alternatively InputComponent => ExtendedComponent
扩展组件
组成 InputComponent
。 ExtendedComponent
就像一个容器。它呈现 InputComponent
,但因为我们返回一个新组件,所以它添加了一个额外的抽象层。您可以使用此层添加状态、行为甚至样式。如果您愿意,您甚至可以决定根本不渲染 InputComponent
— HOC 能够做到这一点以及更多。
下面的图片应该可以消除混乱(如果有的话)。
理论已经讲完了,让我们开始看代码。下面是一个非常简单的 HOC 示例,它将输入组件包装在 <div>
标记周围。从这里开始,我将把 InputComponent
称为 WrappedComponent
,因为这是惯例。不过,您可以随意命名它。
/* The `with` prefix for the function name is a naming convention. You can name your function anything you want as long as it's meaningful */ const withGreyBg = WrappedComponent => class NewComponent extends Component { const bgStyle = { backgroundColor: 'grey', }; render() { return ( <div className="wrapper" style={bgStyle}> <WrappedComponent {...this.props} /> </div> ); } }; const SmallCardWithGreyBg = withGreyBg(SmallCard); const BigCardWithGreyBg = withGreyBg(BigCard); const HugeCardWithGreyBg = withGreyBg(HugeCard); class CardsDemo extends Component { render() { <SmallCardWithGreyBg {...this.props} /> <BigCardWithGreyBg {...this.props} /> <HugeCardWithGreyBg {...this.props /> } }
withGreyBg
函数将一个组件作为输入并返回一个新组件。我们不是直接组合 Card 组件并将样式标签附加到每个单独的组件,而是创建一个 HOC 来实现此目的。高阶组件包装原始组件并在其周围添加 <div>
标签。需要注意的是,这里你必须手动将 props 分两层传递下去。我们没有做任何花哨的事情,但这就是正常的 HOC 的样子。下图更详细地演示了 withGreyBg()
示例。
虽然这目前看起来不是特别有用,但好处并不小。考虑这种情况。您正在使用 React 路由器,并且需要保护某些路由 - 如果用户未经过身份验证,则对这些路由的所有请求都应重定向到 /login
。我们可以使用 HOC 来有效管理受保护的路由,而不是重复身份验证代码。好奇想知道怎么做吗?我们将在下一个教程中介绍这一点以及更多内容。
注意:ECMAScript 中提出了一个称为装饰器的功能,可以轻松使用 HOC。但是,它仍然是一个实验性功能,因此我决定不在本教程中使用它。如果您使用的是 create-react-app,则需要先弹出才能使用装饰器。如果您运行的是最新版本的 Babel (Babel 7),您所需要做的就是安装 <em>babel-preset-stage-0</em>
然后将其添加到 webpack.config.dev.js 的插件列表中,如下所示。
// Process JS with Babel. { test: /\.(js|jsx|mjs)$/, include: paths.appSrc, loader: require.resolve('babel-loader'), options: { // This is a feature of `babel-loader` for webpack (not Babel itself). // It enables caching results in ./node_modules/.cache/babel-loader/ // directory for faster rebuilds. cacheDirectory: true, presets: ['stage-0'] },
在本教程中,我们学习了 HOC 的基本概念。 HOC 是构建可重用组件的流行技术。我们首先讨论基本的 ES6 语法,以便您更容易习惯箭头函数并编写现代 JavaScript 代码。
然后我们了解了高阶函数及其工作原理。最后,我们接触了高阶组件并从头开始创建了 HOC。
接下来,我们将通过实际示例介绍不同的 HOC 技术。在那之前请继续关注。在评论部分分享你的想法。
以上是React 中高阶组件的友好介绍的详细内容。更多信息请关注PHP中文网其他相关文章!