react学习—高阶组件HOC

高阶组件HOC

  • 一、高阶组件HOC
    • 1.高阶组件
    • 2、属性传递
    • 3、使用属性传递
    • 4、注意

一、高阶组件HOC

HOF:Higher-Order Function, 高阶函数,以函数作为参数,并返回一个函数,例如(compose、bind)
HOC: Higher-Order Component, 高阶组件,以组件作为参数,并返回一个组件。
如下例代码B,返回一个新的组件,所以B就是一个高阶组件。

import React from 'react'

export default function withTest(comp) {
     
  return class extends React.Component{
     

  }
}
function A(){
     
  return <h1>test</h1>
}
const B = withTest(A);

1.高阶组件

如果我们要设计一个日志记录组件,那么想想怎样能让这个日志记录组件复用性更高,后期更好维护呢?将整个日志记录组件封装成一个组件?

//withLog.js
import React from 'react'

export default function withLog(Comp) {
     // 使用传入的记录器组件进行记录
  return class LogWarpper extends React.Component {
     // 取个名字方便后期调试
    componentDidMount() {
     
      console.log(`日志:组件${
       Comp.name}被创建了!${
       Date.now()}`);
    }

    componentWillUnmount() {
     
      console.log(`日志:组件${
       Comp.name}被销毁了!${
       Date.now()}`);
    }
    render(){
     
      return <Comp />
    }
  }
}

如下两个记录器A、B,如果想实现两个记录器,那么难以避免造成代码重复,索性交给另一个组件专门去实现如何进行记录,然后调用A,B即可。

//Comp.js
import React from 'react'
export class A extends React.Component{
     // A记录器
  render() {
     
    return <h1>A</h1>
  }
}
export class B extends React.Component{
     // B记录器
  render() {
     
    return <h1>B</h1>
  }
}
import React, {
      Component } from 'react'
import {
     A,B} from './components/Comps'
import withLog from './HOC/withLog'

const ALog = withLog(A);
const BLog = withLog(B);
export default class Input extends Component {
     
  render() {
     
    return (
      <div>
        <ALog />
        <BLog />
      </div>
    )
  }
}

这里就很明显了,A,B只会记录事件,如何记录是LogWarpper的事;两个组件分开也能实现一些功能,组合起来则能产生1+1>2的效果。
react学习—高阶组件HOC_第1张图片
react学习—高阶组件HOC_第2张图片

2、属性传递

组件通过嵌套,那么属性当然也需要我们自己手动一层一层向下传递。

//withLog.js
import React from 'react'

export default function withLog(Comp) {
     
  return class LogWarpper extends React.Component {
     
    componentDidMount() {
     
      console.log(`日志:组件${
       Comp.name}被创建了!${
       Date.now()}`);
    }

    componentWillUnmount() {
     
      console.log(`日志:组件${
       Comp.name}被销毁了!${
       Date.now()}`);
    }
    render(){
     
      return <Comp {
     ...this.props} />
    }
  }
}
//Comps.js
import React from 'react'
export class A extends React.Component{
     
  render() {
     
    return <h1>A:{
     this.props.a}</h1>
  }
}
export class B extends React.Component{
     
  render() {
     
    return <h1>B:{
     this.props.b}</h1>
  }
}
import React, {
      Component } from 'react'
import {
     A,B} from './components/Comps'
import withLog from './HOC/withLog'

const ALog = withLog(A);
const BLog = withLog(B);
export default class Input extends Component {
     
  render() {
     
    return (
      <div>
        <ALog a={
     'a'} />
        <BLog b={
     'b'} />
      </div>
    )
  }
}

在这里插入图片描述
在这里插入图片描述

3、使用属性传递

模拟一个登录系统,只有当提取到登录信息isLogin后才能显示后续页面。

//withLogin
import React from 'react'

export default function withLogin(Comp) {
     
  return function LoginWrapper(props) {
     
    if(props.isLogin){
     
      return <Comp {
     ...props} />
    }
    return null;
  }
}

Comp并未有任何改变

//Comp.js
import React from 'react'
export class A extends React.Component{
     
  render() {
     
    return <h1>A:{
     this.props.a}</h1>
  }
}
export class B extends React.Component{
     
  render() {
     
    return <h1>B:{
     this.props.b}</h1>
  }
}

如果不传isLogin

import React, {
      Component } from 'react'
import {
     A,B} from './components/Comps'
import withLogin from './HOC/withLogin'

const ALog = withLogin(A);
const BLog = withLogin(B);
export default class Input extends Component {
     
  render() {
     
    return (
      <div>
        <ALog a={
     'a'} />
        <BLog b={
     'b'} />
      </div>
    )
  }
}

在这里插入图片描述
传入isLogin后
在这里插入图片描述
是不是发现高阶组件的用处大大的了?其用处当然不止如此,还可以配合我们实现各种复杂的逻辑。

4、注意

如果我们render函数内去包装一个高阶组件呢?

import React, {
      Component } from 'react'
import {
     A,B} from './components/Comps'
import withLog from './HOC/withLog'

export default class Input extends Component {
     
  render() {
     
    const ALog = withLog(A);
    const BLog = withLog(B); 
    return (
      <div>
        <ALog isLogin a={
     'a'} />
        <BLog isLogin b={
     'b'} />
        <button onClick={
     ()=>{
     
          this.setState({
     })
        }}>点击</button>
      </div>
    )
  }
}

react学习—高阶组件HOC_第3张图片
一旦我们对状态进行操作时,你会发现,组件并没有进行重用单独刷新数据,而是整个组件都销毁冲建了。这会对性能造成影响。
此外不要在高阶组件内部更改传入的组件
react学习—高阶组件HOC_第4张图片

你可能感兴趣的:(react学习,react,HOC)