React组件化开发(6)- 高阶组件(6)
13.高阶组件
什么是高阶组件?在学习高阶组件之前,很多人都听说过高阶函数,其实高阶函数和高阶组件非常相似。
回顾一下高阶函数:
高阶函数的维基百科定位:至少满足以下条件之一:
- 接收一个或多个函数作为输入
- 输出一个函数
- JavaScript中比较常见的filter、map、reduce都是高阶函数
13.1什么是高阶组件
那么什么是高阶组件?
- 高阶组件的英文是: Higher-Order Components,简称为 HOC;
- 官网的定义是:高阶组件是参数为组件,返回值为新组件的函数
我们可以进行如下的解析:
- 首先, 高阶组件 本身不是一个组件,而是一个函数;
- 其次,这个函数的参数是一个组件,返回值也是一个组件;
13.2高阶组件的定义
高阶组件的编写:
function enhanceComponent(WraperComponent,) {
return class NewComponent extends PureComponent {
render() {
return (
<WraperComponent {...this.props} />
)
}
}
}
高阶组件的调用:
const NewComponent = enhanceComponent(App);
在给高阶组件传递数据时需要在高阶组件内部进行接收
关于组件名称
- 在es6中,类表达式中类名是可以省略的。(函数也是一样)
高阶组件并不是React API的一部分,它是基于React的组合特性而形成的设计模式。
高阶组件在一些React第三方库中非常常见:
- 比如redux中的connect;
- 比如react-router中的withRouter
13.3高阶组件的应用
一:增强props
import React, { PureComponent } from 'react'
class Home extends PureComponent {
render() {
console.log(this.props);
return (
<h2>Home:{`昵称:${this.props.nickName},等级:${this.props.level} 区域:${this.props.region}`}</h2>
)
}
}
class Footer extends PureComponent {
render() {
return (
<h2>Footer:{`昵称:${this.props.nickName},等级:${this.props.level} 区域:${this.props.region}`}</h2>
)
}
}
function enhanceRegion(WraperComponent) {
return class NewComponent extends PureComponent {
render() {
return <WraperComponent {...this.props} region="中国" />
}
}
}
const EnhanceHome = enhanceRegion(Home);
const EnhanceFooter = enhanceRegion(Footer);
export default class App extends PureComponent {
constructor() {
super();
}
render() {
return (
<div>
App
<EnhanceHome nickName="库里" level={90} />
<EnhanceFooter nickName="追梦格林" level={80} />
</div>
)
}
}
二:增强props默认
import React, { PureComponent, createContext } from 'react'
function Home() {
return (
<UserInfo.Consumer>
{
props => {
return (<div><h2>Home:{`昵称:${props.nickName},等级:${props.level},地区:${props.Region}`}</h2></div>)
}
}
</UserInfo.Consumer>
)
}
function About() {
return (
<UserInfo.Consumer>
{
props => {
console.log(props);
return (<div><h2>About:{`昵称:${props.nickName},等级:${props.level},地区:${props.Region}`}</h2></div>)
}
}
</UserInfo.Consumer>
)
}
const UserInfo = createContext({
nickName: '默认名字',
level: "默认等级",
地区: "默认地区"
});
export default class App extends PureComponent {
render() {
return (
<div>
<UserInfo.Provider value={{ nickName: "斯蒂芬库里", level: 99, Region: "中国" }}>
<Home />
<About />
</UserInfo.Provider>
</div>
)
}
}
三:增强props改进
import React, { PureComponent, createContext } from 'react'
const UserInfo = createContext({
nickName: "默认名",
level: "默认等级",
Region: "默认地区"
})
function Home(props) {
console.log(props);
return (
<div><h2>Home:{`昵称:${props.nickName},等级:${props.level},地区:${props.Region}`}</h2></div>
)
}
function About(props) {
return (
<div><h2>About:Home:{`昵称:${props.nickName},等级:${props.level},地区:${props.Region}`}</h2></div>
)
}
// 定义高阶组件
function enhanceRegion(WrappedComponent) {
return props => {
return (
<UserInfo.Consumer>
{
data => {
return <WrappedComponent {...data} />
}
}
</UserInfo.Consumer>
)
}
}
const EnhanceHome = enhanceRegion(Home);
const EnhanceAbout = enhanceRegion(About);
EnhanceHome()
export default class App extends PureComponent {
render() {
return (
<div>
<UserInfo.Provider value={{ nickName: "斯蒂芬库里", level: 99, Region: "中国" }}>
<EnhanceHome />
<EnhanceAbout />
</UserInfo.Provider>
</div>
)
}
}
四:登录鉴权操作
import React, { PureComponent } from 'react'
function CartPage() {
return <h2>购物车页面</h2>
}
function LoginPage() {
return <h2>需要登录</h2>
}
// 高阶组件
function enhanceIsLogin(WrappedComponent) {
const Cpn = props => {
// console.log(props);
if (props.isLogin) {
return <WrappedComponent />
} else {
return <LoginPage />
}
}
return Cpn;
}
const CartAuth = enhanceIsLogin(CartPage);
export default class extends PureComponent {
render() {
return (
<div>
<CartAuth isLogin={false} />
</div>
)
}
}
五:生命周期劫持
import React, { PureComponent } from 'react'
class Home extends PureComponent {
render() {
return (
<h2>Home</h2>
)
}
}
function enhanceMountTime(WrapeedComponent) {
const NewCpn = class extends PureComponent {
UNSAFE_componentWillMount() {
this.WillMoutTime = Date.now();
}
componentDidMount() {
this.DitMoutTime = Date.now();
const MountTime = this.DitMoutTime - this.WillMoutTime;
console.log(`${WrapeedComponent.name}渲染时间是:${MountTime}`);
}
render() {
return <WrapeedComponent {...this.props} />
}
}
return NewCpn
}
class About extends PureComponent {
render() {
return (
<h2>About</h2>
)
}
}
const MountTimeHome = enhanceMountTime(Home);
const MountTimeAbout = enhanceMountTime(About);
export default class App extends PureComponent {
render() {
return (
<div>
<h3>App</h3>
{/* 计算一个组件创建到挂载完毕的时间 */}
<MountTimeHome />
<MountTimeAbout />
</div>
)
}
}
13.4高阶组件的意义
我们会发现利用高阶组件可以针对某些React代码进行更加优雅的处理
其实早期的React有提供组件之间的一种复用方式是mixin,目前已经不再建议使用:
- Mixin 可能会相互依赖,相互耦合,不利于代码维护
- 不同的Mixin中的方法可能会相互冲突
- Mixin非常多时,组件是可以感知到的,甚至还要为其做相关处理,这样会给代码造成滚雪球式的复杂性
当然,HOC也有自己的一些缺陷:
- HOC需要在原组件上进行包裹或者嵌套,如果大量使用HOC,将会产生非常多的嵌套,这让调试变得非常困难;
- HOC可以劫持props,在不遵守约定的情况下也可能造成冲突;
Hooks的出现,是开创性的,它解决了很多React之前的存在的问题
- 比如this指向问题、比如hoc的嵌套复杂度问题等等;
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
评论已关闭