# react-hoc **Repository Path**: codeResp/react-hoc ## Basic Information - **Project Name**: react-hoc - **Description**: react 高阶组件 Hoc 学习的简单 DEMO. - **Primary Language**: JavaScript - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-01-20 - **Last Updated**: 2022-01-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 高阶组件 ## 官方定义 > 高阶组件(HOC)是 React 中用于**复用组件逻辑**的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。 > HOC 是单词 Heigher Order Component 缩写 具体而言,**高阶组件是参数为组件,返回值为新组件的函数。** ```javascript const EnhancedComponent = higherOrderComponent(WrappedComponent); ``` 从官方定义中,我们可以抽取以下重点: + 高阶组件就是一个函数.(没有说是构造函数,在React中,构造函数,你继承自 React.Component,它就是一个组件了) + 此函数接受一个组件作为参数.(就是接受一个继承自React.Component的构造函数作为参数) + 此函数返回一个组件.(必须返回一个继承自React.Component的构造函数) + ** 逻辑复用**.或者说组件的功能扩展. > 高阶组价,接受一个构造函数,返回一个构造函数. 所以,高阶组件就是一个概念. 它本质上也是高阶函数. > react-redux 里面的 connect 函数,就是一个高阶组件. ![截屏2022-01-20 下午4.40.13](assets/%E6%88%AA%E5%B1%8F2022-01-20%20%E4%B8%8B%E5%8D%884.40.13.png) --- ## 理解高阶组件. > 既然高阶组件,本质上是一个函数.那么我就给它一个组件作为入参,在返回一个组件即可. ```JavaScript import React, { useState } from 'react' import './App.css'; /** * * 官方定义高阶组件(HOC)是 React 中用于**复用组件逻辑**的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。 HOC 是单词 Heigher Order Component 缩写 具体而言,高阶组件是参数为组件,返回值为新组件的函数。 * * */ function HelloComponent(props) { return (

我是一个定义的函数式组件 {props.title}

) } // 高阶组件就是一个函数,接收一个组件,返回一个[新]的组件. const withComponent = (Component) => { return function WrapperComponent() { const [title, setTitle] = useState('这是由内部组件 WrapperComponent 传递过来的 title') const changeTitle = () => { setTitle("这是新的 title") } return ( ) } } // 传入一个HelloComponent,作为入参 // 返回一个HocComponent作为新的组件 const HocComponent = withComponent(HelloComponent) function App() { return (

Hello HOC - Highter Order Component

); } export default App; ``` 可以正常工作. ![截屏2022-01-20 下午7.48.43](assets/%E6%88%AA%E5%B1%8F2022-01-20%20%E4%B8%8B%E5%8D%887.48.43.png) --- ## 将逻辑复用(功能扩展)逻辑设定在高阶组件中. 上述例子,仅演示了高阶组件的用法和原理. 这次,我们把逻辑复用和功能扩展加上去. 这么一个例子 + 有两组件. `Foo` 和 `Bar`. + `Foo` 和 `Bar` 组件的功能就是在屏幕视口宽度发生改变是,动态的把宽度数值显示出来. ```javascript import React from 'react' import './App.css'; /** * * 官方定义高阶组件(HOC)是 React 中用于**复用组件逻辑**的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。 HOC 是单词 Heigher Order Component 缩写 具体而言,高阶组件是参数为组件,返回值为新组件的函数。 * * */ class Foo extends React.PureComponent { state = { sw: document.documentElement.clientWidth } componentDidMount () { window.addEventListener('resize', () => { this.setState(() => ({ sw: document.documentElement.clientWidth })) }, false) } componentWillUnmount () { window.removeEventListener('resize') } render () { return (

当前的屏幕宽度为:{this.state.sw}

) } } class Bar extends React.PureComponent { state = { sw: document.documentElement.clientWidth } componentDidMount () { window.addEventListener('resize', () => { this.setState(() => ({ sw: document.documentElement.clientWidth })) }, false) } componentWillUnmount () { window.removeEventListener('resize') } render () { return ( ) } } function App () { return (

Hello HOC - Highter Order Component

); } export default App; ``` 效果如图: ![组件逻辑重复了](assets/%E7%BB%84%E4%BB%B6%E9%80%BB%E8%BE%91%E9%87%8D%E5%A4%8D%E4%BA%86.gif) 功能确实实现了.但是两组件除了渲染的位置,其他地方都是一致的. 在`Vue`中,我们可以使用 `mixins` 来解决组件间逻辑重复定义的问题. > `state , componentDidMount, componentWillUnmount` 逻辑重复. 在 `React` 中,我们就可以使用 `Highter Order Component` 高阶组件的方式,来抽取组件重复定义的逻辑部分. ```javascript // 定义一个高阶组件函数,来抽取逻辑重复的位置,提高逻辑复用. const withResize = (Component) => { //xxxxx } ``` 具体代码如下: ```javascript import React from 'react' import './App.css'; /** * * 官方定义高阶组件(HOC)是 React 中用于**复用组件逻辑**的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。 HOC 是单词 Heigher Order Component 缩写 具体而言,高阶组件是参数为组件,返回值为新组件的函数。 * * */ class Foo extends React.PureComponent { // state = { // sw: document.documentElement.clientWidth // } // componentDidMount () { // window.addEventListener('resize', () => { // this.setState(() => ({ sw: document.documentElement.clientWidth })) // }, false) // } // componentWillUnmount () { // window.removeEventListener('resize') // } render () { return (

当前的屏幕宽度为:{this.props.sw}

) } } class Bar extends React.PureComponent { // state = { // sw: document.documentElement.clientWidth // } // componentDidMount () { // window.addEventListener('resize', () => { // this.setState(() => ({ sw: document.documentElement.clientWidth })) // }, false) // } // componentWillUnmount () { // window.removeEventListener('resize') // } render () { return ( ) } } // 定义一个高阶组件函数,来抽取逻辑重复的位置,提高逻辑复用. const withResize = (Component) => { return class WrappedComponent extends React.PureComponent { //#region 抽离组件通用的逻辑部分 state = { sw: document.documentElement.clientWidth } componentDidMount () { window.addEventListener('resize', () => { this.setState(() => ({ sw: document.documentElement.clientWidth })) }, false) } componentWillUnmount () { window.removeEventListener('resize') } //#endregion render () { // 将需要的数据以 props 的方式传递给被包装的组件 return } } } const FooWithResize = withResize(Foo) const BarWithResize = withResize(Bar) function App () { return (

Hello HOC - Highter Order Component

将通用逻辑抽离,以便复用!

{/* */}
); } export default App; ``` + 将通用逻辑从 `Foo` 和 `Bar` 组件中抽离.起到逻辑复用的作用. + 将 `Foo` 和 `Bar` 需要的数据以 `props` 的形式传入即可. 效果和上述是一致的. ![高阶组件抽取通用逻辑以便复用](assets/%E9%AB%98%E9%98%B6%E7%BB%84%E4%BB%B6%E6%8A%BD%E5%8F%96%E9%80%9A%E7%94%A8%E9%80%BB%E8%BE%91%E4%BB%A5%E4%BE%BF%E5%A4%8D%E7%94%A8.gif) --- ## 总结 + 高阶组件就是一个函数仅此而已(`javascript`中不就是函数和对象吗?) + 高阶组件接受一个组件(可以是函数组件,也可以是class 组件)作为参数(普通函数,构造函数). + 返回一个新组件(可以是函数组件,也可是 class 组件),返回一个普通函数或者是构造函数. + 所以高阶组件也是一个高阶函数. + 将通用的逻辑抽离在高阶组件中,已达到复用的目的.