高阶组件
- Higher-Order Components就是一个函数,传给它一个组件(参数是组件),它返回一个新的组件(返回值是组件)
- 作用:对原有的组件的扩展
const NewComponent = higherOrderComponent(YourComponent)
- 比如,我们想要我们的组件通过自动注入一个版权信息。
withCopyright.jsx
文件定义一个高阶组件
//版权的高阶组件 hoc
import React, { Component } from 'react';
//参数: 组件
const withCopy = (WrappedComponent) => {
//返回一个新组件
return class NewComponent extends Component {
render() {
return (
<>
{/* {...this.props} 将 App的props的值接收并解构 */}
<WrappedComponent title="版权信息" {...this.props} />
<div>© 版权所有:LS</div>
</>
)
}
}
}
export default withCopy;
App.jsx
组件使用方式
import React,{Component} from 'react';
// 引入高阶组件
import withCopy from './withCopy';
class App extends Component{
constructor(props){
super(props);
this.state = {};
}
componentDidMount(){
console.log(this.props);
}
render(){
return (<>
根节点
</>)
}
}
export default withCopy(App);
index.js
文件 在App调用上传了参数
import ReactDOM from 'react-dom'
import App from './HOC/App';
ReactDOM.render(
<App msg='3' />,
document.getElementById('root')
)
- 这样只要我们有需要用到版权信息的组件,都可以直接使用
withCopyright
这个高阶组件包裹即可。
应用场景
- 进行权限判断:
页面中的按钮权限,在高阶组件中实现权限判断,页面权限判断,进行路由跳转 - 日志记录:
逻辑提取出来,封装成高阶组件,如果哪个组件需要进行日志处理,在组件名的外面包裹一层日志高阶组件 - 数据校验:
多个地方都需要进行校验数据,将逻辑拆出来,封装成高阶组件 - 异常处理:
进行封装异常处理,例如:异常时来个弹窗报错
- 高阶组件实例:权限判断
- 需求:一个admin(管理员),一个user(普通用户)
- 要求:管理员进入页面,按钮就可见,普通用户进页面,按钮不可见
- 使用高阶组件解决这种需求经常变化,而且多个地方都需要鉴权的情况
withAuth.jsx
文件
//作用 ,判断权限,返回是否有权限的按钮信息
import React, { Component } from 'react';
const withAuth = (WrappedComponent) => {
//返回一个新组件
return class NweComponent extends Component {
render() {
if (this.props.author === "admin") {
return <WrappedComponent {...this.props} />
} else {
return null;
}
}
}
}
export default withAuth;
Button.jsx
文件
//按钮组件
import React, { Component } from 'react';
import withAuth from './withAuth';
class Button extends Component {
constructor(props) {
super(props);
this.state = {}
}
render() {
return (<button >{this.props.children}</button>);
}
}
export default withAuth(Button);
App.jsx
文件
import React, { Component } from 'react';
import Button from './Button';
//模拟权限用户数据
function getAuthor() {
return new Promise((resolve, reject) => {
setTimeout(() => {
//取个0-1之间的随机数
let index = Math.round(1 - Math.random());
let author = ['admin', 'user'][index];
resolve(author)
}, 1000)
})
}
class App extends Component {
constructor(props) {
super(props);
this.state = {
author: ''
}
}
async componentDidMount() {
let author = await getAuthor();
this.setState({ author: author })
}
render() {
const { author } = this.state;
return (
<div>
<h1>欢迎 {author} 登录本系统!!</h1>
<Button author={author}>新增用户</Button>
<Button author={author}>删除用户</Button>
<Button author={author}>修改用户密码</Button>
<Button author={author}>冻结用户</Button>
</div>
);
}
}
export default App;
index.js
文件
import ReactDOM from 'react-dom'
import App from './HOC/App';
ReactDOM.render(
<App />,
document.getElementById('root')
)
- 刷新页面
高阶组件的特点:
- 高阶组件就是把某个组件装饰成一个新的组件,对功能进行了扩展
- 高阶组件进行了代码复用,封装,有利于解耦,增强了灵活性
- 核心思想:装饰器模式
装饰器是ES7的语法:可以对类、方法属性进行包装,包装后就在原有的基础上增加了一些新特性
高阶组件,装饰的对象是一个类
- 需要先配置文件,才能使用装饰器
- 配置教程请参考我的另一篇博客
- 使用装饰器重新
Button.jsx
文件
//按钮组件
import React, { Component } from 'react';
import withAuth from './withAuth';
//装饰器的语法更优雅
@withAuth
class Button extends Component {
constructor(props) {
super(props);
this.state = {}
}
render() {
return (<button >{this.props.children}</button>);
}
}
export default Button;