1. 前言
1.高阶组件是
react
组件总结中最难的一种,平常基本用不到,就算能用到也给规避了,所以也导致很多人不会2.这几天结合之前的一些粗浅经验,搞了个简单的梳理,最终梳理出几个相对简单易懂的课件,不足之处,欢迎交流
2. 是什么 what
高阶组件(Higher Order Component,简称:HOC ):
1.是 React 中用于
重用组件逻辑
的高级技巧.2.HOC 自身
不是
ReactAPI
的一部分,它是一种基于 React 的组合特性
而形成的设计模式
3.高阶
组件
是参数
为组件,返回值为新组件的函数
。
简单理解
一个高阶组件只是一个包装了另外一个 React 组件的 组件。
这种形式通常实现为一个函数,本质上是一个类工厂(class factory
3.优点
1.实现了对原有组件的
增强和优化
,2.可以对原有
组件
中的state, props和逻辑执行增删改操作, 一般用于代码重用
和组件增强优化
4. 应用场景
- 需要代码重用时, react如果有多个组件都用到了
同一段逻辑
, 这时,就可以把共同的逻辑部分提取出来,利用高阶组件的形式将这段逻辑整合到每一个组件中, 从而减少代码的逻辑重复- 需要组件
增强优化时
, 比如我们在项目中使用的组件有些不是自己写的, 而是从网上撸下来的,但是第三方
写的组件可能比较复杂, 有时不能完全满足需求, 但第三方组件不易修改, 此时也可以用高阶组件,在不修改原始组件的前提下, 对组件添加满足实际开发需求的功能
3.其实主要就是针对优点 的应用
4.也可以用来替换mixins
混入
5. 组件和 高阶组件的区别
1.组件是将 props 转换为 UI
2.高阶组件是将组件转换为另一个组件
6. 实现方式
6.1 属性代理
(Props Proxy): 通过创建新组件来包裹原始组件, 把原始组件作为新组件的子组件渲染
功能: 可实现对原始组件的 props数据更新 和 组件模板更新
6.2 反向继承
(Inheritance Inversion): 通过创建新组件继承自原始组件, 把原始组件作为父组件
功能: 可实现对原始组件的state状态数据更新 和 组件模板更新
好了已经一大堆理论了,上代码 再接着理论
7. 铺垫 引出工作/代码
7.1 代码
localStorage.setItem("userInfo", JSON.stringify({ name: "yzs", description: "生活如此多娇" })) class UserView extends React.Component { constructor(props) { super(props) this.state = { userInfo: {} } } componentDidMount() { let userInfo = JSON.parse(localStorage.getItem("userInfo")) this.setState({ userInfo }) } render() { let { userInfo } = this.state return ( <div> <h1>{userInfo.name}</h1> <p>{userInfo.description}</p> </div> ) } }
7.2 分析
1.上述 获取
userInfo
的逻辑要在好多地方使用,2.那么在使用的地方都需要重写 constructor componentDidMount ,显然这是冗余操作
3.这个时候需要代码 重用,所以可以选择高阶组件,对应上述的优点之一
8. 属性代理 用法
高阶函数的基本结构是 函数,参数是组件,返回新的组件
所以基本写法都是差不多的
8.1 基本结构
function withUserData(WrappedComponent) { return class extends React.Component { constructor(props) { super(props) this.state = { userInfo: {} } } componentDidMount() { let userInfo = JSON.parse(localStorage.getItem("userInfo")) this.setState({ userInfo }) } render() { // ...this.props 传递给当前组件的属性继续向下传递 return <WrappedComponent userInfo={this.state.userInfo} {...this.props} /> } } }
8.2 分析
1.函数名字可以随便起
2.参数名一般都是
WrappedComponent
, ed代表被包裹 ,所以整体代表 被包裹的组件,
注意
3.这里只封装了获取
userInfo
数据的逻辑,render
,布局可以不管4.然后以属性的形式传递给包装的组件
WrappedComponent
5.
WrappedComponent
中直接通过props
属性获取需要的数据6.其他组件也需要这段逻辑时就可以通过
withUserData
高阶组件包装组件来使用
拔高
1.高阶组件的主要功能是封装并分离组件的通用逻辑,让通用逻辑在组件间更好地被复用。
2.高阶组件的这种实现方式,本质上是一个装饰者设计模式。
9. 使用高阶组件
9.1 需要使用的组件
class UserView2 extends React.Component { render() { // 注意这里变为 props属性接收传值 let { userInfo } = this.props return ( <div> <h1>{userInfo.name}</h1> <p>{userInfo.description}</p> </div> ) } // 省略其他逻辑,重点是当前知识点 }
这个组件也需要用到获取
userInfo
数据的逻辑
9.2 和高阶组件联合使用
const UserHOC = withUserData(UserView2)
函数调用,参数是组件
9.3 显示
let App = () => { return ( <div> <h1>App</h1> <UserView /> <UserHOC /> </div> ) } ReactDOM.render(<App />, document.querySelector("#app"))
直接作为组件来使用
10. 高阶组件与父组件区别
这里很多道友有疑问了,这不和父组件一样嘛干啥这么麻烦呢
1.首先从逻辑的执行流程上来看,高阶组件确实和父组件比较相像,
2.但是
高阶
组件强调的是逻辑
的抽象。高阶组件是一个函数
,函数关注的是逻辑;3.
父组件
是一个组件,组件主要关注的是UI/DOM
。如果逻辑是与DOM直接相关的,那么这部分逻辑适合放到父组件中实现;4.如果逻辑是与DOM不直接相关的,那么这部分逻辑适合使用高阶组件抽象,如数据校验、请求发送等。
11.后续
看来一篇文章还真不行,接着写