React的高阶组件(HOC)
1. 概念
高阶组件和高阶函数的类似,使用函数接收一个组件,并返回一个组件。
function withList(WrapComponent) {return class extends Component {render() {return <div><WrapComponent {...this.props}/></div>;}}
};
高阶组件主要用作于逻辑的封装、拦截渲染、拦截生命周期:获取渲染性能,日志打点等,安按照实现方式可以分为属性代理和反向继承两种。
2. 属性代理
属性代理的作用:
- 代理props
- 条件渲染
- 添加状态(state)
- 封装一些通用的逻辑
2.1 代理props
function withList(WrapComponent) {const data = [{ id: '1', text: '测试1' }, { id: '2', text: '测试2' }, { id: '3', text: '测试3' }, { id: '4', text: '测试4' }, { id: '5', text: '测试5' }]return class extends Component {render() {return <div>{this.props.data.length > 0 ? <WrapComponent {...this.props} data={data} /> : <span>{emptyText}</span>}</div>;}}
};class List extends Component {render() {return (<ul>{this.props.data.map(item => {return <li key={item.id}>{item.text}</li>})}</ul>)}
};export default withList(List);
2.2 条件渲染
function withList(WrapComponent, emptyText) {return class extends Component {render() {return <div>{this.props.data.length>0 ? <WrapComponent {...this.props}/> : <span>{emptyText}</span>}</div>;}}
};class List extends Component {render() {return (<ul>{this.props.data.map(item => {return <li key={item.id}>{item.text}</li>})}</ul>)}
};export default withList(List,'暂无数据');
2.3 添加状态
利用这一点可以将非受控组件转为受控组件
import React, { Component } from 'react'class Input extends Component {render() {return (<input value={this.props.value} />)}
};function withInput(WrapComponent) {return class extends Component {state = {value: this.props.value}onChange = (value) => {this.setState({ value });}render() {return <WrapComponent {...this.props} value={this.state.value} onChange={this.onChange}/>;}}
};export default withInput(Input);
3. 反向继承
反向继承的作用
- 拦截渲染
- 代理props
- 劫持生命周期函数
- 操作state
- 修改react树
3.1 拦截渲染
function withList(WrapComponent) {return class extends WrapComponent {render() {return <div><span>通过反向继承拦截渲染</span>{super.render()}</div>;}}
};
3.2 劫持生命周期
function withList(WrapComponent) {return class extends WrapComponent {componentDidMount(){if(super.componentDidMount){super.componentDidMount.apply(this);};console.log('拦截生命周期');}render() {return <div><span>通过反向继承拦截渲染</span>{super.render()}</div>;}}
};
3.3 操作state
import React, { Component } from 'react';function withList(WrapComponent) {return class extends WrapComponent {constructor(props) {super(props);this.state.data = []; //将列表数据置空}render() {return <div>{super.render()}</div>}}
};class List extends Component {state = {data: [{ id: '1', text: '测试1' }, { id: '2', text: '测试2' }, { id: '3', text: '测试3' }, { id: '4', text: '测试4' }, { id: '5', text: '测试5' }],}render() {return (<ul>{this.state.data.map(item => {return <li key={item.id}>{item.text}</li>})}</ul>)}
};export default withList(List);
3.4 修改react树
import React, { Component } from 'react';function withList(WrapComponent) {return class extends WrapComponent {render() {const tree = super.render();let newProps = { ...tree.props };if (tree.type === 'ul') {newProps.value = 'value';}return React.cloneElement(tree, newProps, newProps.children);}}
};class List extends Component {render() {return (<ul>{this.props.data.map(item => {return <li key={item.id}>{item.text}</li>})}</ul>)}
};export default withList(List);
3.5 记录渲染性能
function withTime(WrapComponent) {return class extends WrapComponent {constructor(props) {super(props);this.start = 0;this.end = 0}componentWillMount() {if (super.componentWillMount) {super.componentWillMount.call(this);};this.start = Date.now();}componentDidMount() {if (super.componentDidMount) {super.componentDidMount.call(this);};this.end = Date.now();console.log(`渲染的时间为:${(this.end - this.start) / 1000}秒`)}render() {return super.render();}}
};
4. 使用装饰器
4.1 安装和配置
首先执行npm run eject暴露出webpack配置,然后安装装饰器插件
yarn add @babel/plugin-proposal-decoreators;
最后在package.json中的babel配置中添加一下配置然后重新项目
"babel": {"presets": ["react-app"],"plugins":[["@babel/plugin-proposal-decorators",{"legacy":true}]]}
配置完之后如果有报红需要配置一下:
文件-> 首选项 -> 搜索 ExperimentalDecorators 勾选上之后红线就消失了
4.2 使用
@withList
class List extends Component {render() {return (<ul>{this.props.data.map(item => {return <li key={item.id}>{item.text}</li>})}</ul>)}
};
5.总结
- 高阶组件的作用有代复用、代理属性、拦截渲染、劫持生命周期
- 反向继承能直接操作和拦截组件的state和生命周期,功能比属性代理更加强大
React的高阶组件(HOC)相关推荐
- [react] 使用高阶组件(HOC)实现一个loading组件
[react] 使用高阶组件(HOC)实现一个loading组件 function HOC(wrappedComponent) {return class extends React.Componen ...
- react学习—高阶组件HOC
高阶组件HOC 一.高阶组件HOC 1.高阶组件 2.属性传递 3.使用属性传递 4.注意 一.高阶组件HOC HOF:Higher-Order Function, 高阶函数,以函数作为参数,并返回一 ...
- React Native高阶组件(HOC)模型理论与实践
什么是HOC? HOC(全称Higher-order component)是一种React的进阶使用方法,主要还是为了便于组件的复用.HOC就是一个方法,获取一个组件,返回一个更高级的组件. 什么时候 ...
- [react] 高阶组件(HOC)有哪些优点和缺点?
[react] 高阶组件(HOC)有哪些优点和缺点? HOC 优点 通过传递props去影响内层组件的状态,不直接改变内层组件的状态,降低了耦合度 缺点 组件多层嵌套, 增加复杂度与理解成本 ref隔 ...
- [react] 举例说明什么是高阶组件(HOC)的反向继承
[react] 举例说明什么是高阶组件(HOC)的反向继承 import React from 'react';const hoc = (WrappedComponent) => {// 集成需 ...
- [react] 举例说明什么是高阶组件(HOC)的属性代理
[react] 举例说明什么是高阶组件(HOC)的属性代理 function HOC(WrappedComponent) {return class HOC extends Component {re ...
- 「react进阶」一文吃透React高阶组件(HOC)
一 前言 React高阶组件(HOC),对于很多react开发者来说并不陌生,它是灵活使用react组件的一种技巧,高阶组件本身不是组件,它是一个参数为组件,返回值也是一个组件的函数.高阶作用用于强化 ...
- React 高阶组件HOC使用总结
HOC(高阶组件) /*HOC(高阶组件): 接收一个组件,返回包装后的组件(增强组件)- 不是React API- 是一种设计模式,类似于装饰器模式- ≈ Mixin && > ...
- react 高阶组件hoc使用
react 高阶组件hoc使用 1. 为什么使用高阶组件 2. 具体使用 2.1原代码: 2.2 使用hoc封装后 1. 为什么使用高阶组件 高阶组件(HOC)是 React 中用于复用组件逻辑的一种 ...
最新文章
- Eclipse SVN冲突详细解决方案
- 戴尔r720服务器增加内存,dell r720服务器加了一根内存后,开机显示configuring memory,卡在这里进不了系统,请问这是什么情况?...
- [转载](热议)“我不伟大”,但可以让善良“春暖花开”
- Android书页翻页设计:android-flip
- Oculus cv1 input
- 北京理工大学计算机学院研究生培养方案,北京理工大学2018版学术型研究生培养方案.PDF...
- python flask服务器假死_python – Flask POST请求导致服务器崩溃
- libz.so.1: cannot open shared object file: No such file or directory
- 增加批量修改成本价格,配合后台管理增加成本价和毛利润统计
- C#Winform使用火狐firefox内核GeckoWebBrowser
- 浅析企业上下级沟通的障碍及对策
- 【Web】lighttpd基础
- 地图图像迁移研究与实现
- 视频剪辑 - Pr入门[第一次学习] - 小白蜕变!!!
- 递推数列【清华大学】
- 其他算法和思想的题目
- javascript学习路线图
- 一个好用的流氓软件清理工具合集
- 聊QQ时,系统消息提示“被迫下线”怎么回事
- INTEL CPU型号详解分类:电脑硬件