react组件封装之三剑客(HOC、Render Props、Hook)

封装组件必然是为了逻辑复用,那么下面我们通过使用不同的封装方式去封装一个猫(HOC)、鼠(Render Props)、狗(Hook)跟着鼠标移动的逻辑组件,来看看组件封装的奥妙。

一:HOC(高阶组件)

高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。

 高阶组件其实就是一个参数是组件,返回值是新组件的函数。

import React from "react";

// HOC withSubscription 函数  WrappedComponent 需要被封装的组件
const withSubscription = WrappedComponent => {
    return class WithSubscription  extends React.Component {
        constructor(props) {
            super(props)
            this.state = {
                x: 0,
                y: 0,
            }
        }
        // 获取位置信息
        getSite = (e) => {
            this.setState({
                x: e.clientX,
                y: e.clientY,
            })
        } 

        componentDidMount() {
            document.addEventListener('mousemove', this.getSite)
        }

        componentWillUnmount() {
            document.removeEventListener('mousemove', this.getSite)
        }

        render() {
            return (
                <WrappedComponent {...this.props} {...this.state} />
            )
        }
    }
}

// 对 CatTracker 进行装饰, 使其获得获取位置信息的能力
@withSubscription
class CatTracker extends React.Component {
    constructor(props) {
        super(props)
    }

    render() {
        const {x, y} = this.props
        return <div style={{position: 'absolute', left: x, top: y }}>猫</div>
    }
}

export default CatTracker

 二:Render Props

Render Props是指一种在 React 组件之间使用一个值为函数的 prop 共享代码的简单技术

import React from "react";

function Cat(Props) {
  const { x, y } = Props.mouse;
  return <div style={{ position: "fixed", left: x + 50, top: y + 50 }}>鼠</div>;
}

class Mouse extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      x: 0,
      y: 0,
    };
  }
  // 获取位置信息
  getSite = (e) => {
    this.setState({
      x: e.clientX,
      y: e.clientY,
    });
  };

  componentDidMount() {
    document.addEventListener("mousemove", this.getSite);
  }

  componentWillUnmount() {
    document.removeEventListener("mousemove", this.getSite);
  }

  render() {
    return (
      <div>
        {this.props.render(this.state)}
      </div>
    );
  }
}

function MouseTracker() {
  return (
    <>
      <h1>鼠标!</h1>
      <Mouse render={(mouse) => <Cat mouse={mouse} />} />
    </>
  );
}

export default MouseTracker;

通过props传递组件,有点类似slot的思想

 

三:Hook

Hook作用于函数组件,且我们可以使用自定义Hook.

import { useState, useEffect } from "react";

const useDog = () => {
    const [x, setX] = useState(0)
    const [y, setY] = useState(0)

    // 获取位置信息
    const getSite = (e) => {
        setX(e.clientX)
        setY(e.clientY)
    }

    useEffect(() => {
        document.addEventListener('mousemove', getSite)
        return () => {
            document.removeEventListener('mousemove', getSite)
        }
    })

    return {
        x,
        y
    }
}

const DogTracker = () => {
    const site = useDog()
    return (
        <div style={{position: 'fixed', left: site.x + 100, top: site.y + 100}}>狗</div>
    )
}

export default DogTracker

 通过对同一逻辑进行不同方式的封装,Hook无疑看起来逻辑更清晰,复用更简单,而函数组件也更符合react的设计初衷。

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值