react 高价组件HOC实现组件复用

目录

一 使用步骤

二 显示鼠标坐标

 三 鼠标随图片移动

四 设置displayName

五 传递props


高阶组件HOC: Higher-Order Component,是一个函数,接收要包装的组件,返回增强后的组件
目的:实现状态逻辑复用
高阶组件就相当于手机壳, 采用包装(装饰)模式

一 使用步骤


1 创建一个函数,名称约定以with开头
2 指定函数的参数,参数以大写字母开头(作为要渲染的组件)
3 在函数内部创建一个类组件,提供复用的状态逻辑代码,并返回
4 渲染参数组件,同时将状态通过props传递给参数组件
5 调用该高阶组件,传入要增强的组件,通过返回值拿到增强后的组件,并将其渲染到页面中

二 显示鼠标坐标

import React from "react";
import ReactDOM from "react-dom";

// 1 创建一个函数,名称约定以with开头
// 2 指定函数的参数,参数以大写字母开头(作为要渲染的组件)
function withMouse(WrappedComponent) {

    // 3 在函数内部创建一个类组件,提供复用的状态逻辑代码,并返回
    class Mouse extends React.Component {

        //鼠标状态
        state = {
            x: 0,
            y: 0
        }

        //处理状态的逻辑代码
        handleMouseMove = e => {
            this.setState({
                x: e.clientX,
                y: e.clientY
            })
        }

        //监听鼠标移动事件
        componentDidMount() {
            window.addEventListener("mousemove", this.handleMouseMove)
        }

        //解绑事件
        componentWillUnmount() {
            window.removeEventListener('mousemove', this.handleMouseMove)
        }

        render() {
            //4 渲染参数组件,同时将状态通过props传递给参数组件
            return <WrappedComponent {...this.state}/>

        }

    }
    return Mouse;
}

const Position = props => (
    <p>
        鼠标当前位置:(x:{props.x},y:{props.y})
    </p>
)

//调用该高阶组件,传入要增强的组件,通过返回值拿到增强后的组件,并将其渲染到页面中
const MousePosition = withMouse(Position)

class App extends React.Component {

    render() {
        return (
            <div>
                {/*渲染增强后的组件*/}
                <MousePosition/>
            </div>)
    }
}

ReactDOM.render(<App/>, document.getElementById("root"));

效果

 三 鼠标随图片移动

加入鼠标随图片移动的功能

import imgage from "./images/cat.jpg"

const Cat = props => (
    <img src={imgage} alt='猫' style={
   
   {
        position: 'absolute',
        // 为了让鼠标在图片的中间,top减掉了图片的一半高度,left减掉了图片一半的宽度
        top: props.y - 180,
        left: props.x - 180
    }}/>
)


//调用该高阶组件,传入要增强的组件,通过返回值拿到增强后的组件,并将其渲染到页面中
const MousePosition1 = withMouse(Cat)

效果

完整代码

import React from "react";
import ReactDOM from "react-dom";
import imgage from "./images/cat.jpg"

// 1 创建一个函数,名称约定以with开头
// 2 指定函数的参数,参数以大写字母开头(作为要渲染的组件)
function withMouse(WrappedComponent) {

    // 3 在函数内部创建一个类组件,提供复用的状态逻辑代码,并返回
    class Mouse extends React.Component {

        //鼠标状态
        state = {
            x: 0,
            y: 0
        }

        //处理状态的逻辑代码
        handleMouseMove = e => {
            this.setState({
                x: e.clientX,
                y: e.clientY
            })
        }

        //监听鼠标移动事件
        componentDidMount() {
            window.addEventListener("mousemove", this.handleMouseMove)
        }

        //解绑事件
        componentWillUnmount() {
            window.removeEventListener('mousemove', this.handleMouseMove)
        }

        render() {
            //4 渲染参数组件,同时将状态通过props传递给参数组件
            return <WrappedComponent {...this.state}/>

        }

    }
    return Mouse;
}


const Cat = props => (
    <img src={imgage} alt='猫' style={
   
   {
        position: 'absolute',
        // 为了让鼠标在图片的中间,top减掉了图片的一半高度,left减掉了图片一半的宽度
        top: props.y - 125,
        left: props.x - 100
    }}/>
)


//调用该高阶组件,传入要增强的组件,通过返回值拿到增强后的组件,并将其渲染到页面中
const MousePosition1 = withMouse(Cat)

const Position = props => (
    <p>
        鼠标当前位置:(x:{props.x},y:{props.y})
    </p>
)

//调用该高阶组件,传入要增强的组件,通过返回值拿到增强后的组件,并将其渲染到页面中
const MousePosition2 = withMouse(Position)

class App extends React.Component {

    render() {
        return (
            <div>
                {/*渲染增强后的组件*/}
                <MousePosition1/>
                <MousePosition2/>
            </div>)
    }
}

ReactDOM.render(<App/>, document.getElementById("root"));

四 设置displayName

默认情况下,react使用组件名称作为displayName
使用高阶组件存在的问题: 得到的两个组件名称相同


解决办法: 设置displayName → 用于调试时区分不同的组件

 效果

完整代码

import React from "react";
import ReactDOM from "react-dom";
import imgage from "./images/cat.jpg"

// 1 创建一个函数,名称约定以with开头
// 2 指定函数的参数,参数以大写字母开头(作为要渲染的组件)
function withMouse(WrappedComponent) {

    // 3 在函数内部创建一个类组件,提供复用的状态逻辑代码,并返回
    class Mouse extends React.Component {

        //鼠标状态
        state = {
            x: 0,
            y: 0
        }

        //处理状态的逻辑代码
        handleMouseMove = e => {
            this.setState({
                x: e.clientX,
                y: e.clientY
            })
        }

        //监听鼠标移动事件
        componentDidMount() {
            window.addEventListener("mousemove", this.handleMouseMove)
        }

        //解绑事件
        componentWillUnmount() {
            window.removeEventListener('mousemove', this.handleMouseMove)
        }

        render() {
            //4 渲染参数组件,同时将状态通过props传递给参数组件
            return <WrappedComponent {...this.state}/>

        }

    }

    //设置displayName
    Mouse.displayName = `withMouse${getDisplayName(WrappedComponent)}`
    return Mouse;
}
//displayName
function getDisplayName(WrappedComponent) {
    return WrappedComponent.displayName || WrappedComponent.name || 'Component'
}

const Cat = props => (
    <img src={imgage} alt='猫' style={
   
   {
        position: 'absolute',
        // 为了让鼠标在图片的中间,top减掉了图片的一半高度,left减掉了图片一半的宽度
        top: props.y - 125,
        left: props.x - 100
    }}/>
)


//调用该高阶组件,传入要增强的组件,通过返回值拿到增强后的组件,并将其渲染到页面中
const MousePosition1 = withMouse(Cat)

const Position = props => (
    <p>
        鼠标当前位置:(x:{props.x},y:{props.y})
    </p>
)

//调用该高阶组件,传入要增强的组件,通过返回值拿到增强后的组件,并将其渲染到页面中
const MousePosition2 = withMouse(Position)

class App extends React.Component {

    render() {
        return (
            <div>
                {/*渲染增强后的组件*/}
                <MousePosition1/>
                <MousePosition2/>
            </div>)
    }
}

ReactDOM.render(<App/>, document.getElementById("root"));

五 传递props

问题:

添加了一个属性, 打印了props

 属性没显示在props里

 

原因:props传递丢失

解决办法:

 效果

 完整代码

import React from "react";
import ReactDOM from "react-dom";


// 1 创建一个函数,名称约定以with开头
// 2 指定函数的参数,参数以大写字母开头(作为要渲染的组件)
function withMouse(WrappedComponent) {

    // 3 在函数内部创建一个类组件,提供复用的状态逻辑代码,并返回
    class Mouse extends React.Component {

        //鼠标状态
        state = {
            x: 0,
            y: 0
        }

        //处理状态的逻辑代码
        handleMouseMove = e => {
            this.setState({
                x: e.clientX,
                y: e.clientY
            })
        }

        //监听鼠标移动事件
        componentDidMount() {
            window.addEventListener("mousemove", this.handleMouseMove)
        }

        //解绑事件
        componentWillUnmount() {
            window.removeEventListener('mousemove', this.handleMouseMove)
        }

        render() {
            //4 渲染参数组件,同时将状态通过props传递给参数组件
            return <WrappedComponent {...this.state}{...this.props}/>

        }

    }

    return Mouse;
}


const Position = props => {
    console.log(props)
    return (
        <p>
            鼠标当前位置:(x:{props.x},y:{props.y})
        </p>
    )

}

//调用该高阶组件,传入要增强的组件,通过返回值拿到增强后的组件,并将其渲染到页面中
const MousePosition = withMouse(Position)

class App extends React.Component {

    render() {
        return (
            <div>
                {/*渲染增强后的组件*/}
                <MousePosition a="1"/>
            </div>)
    }
}

ReactDOM.render(<App/>, document.getElementById("root"));

猜你喜欢

转载自blog.csdn.net/m0_45877477/article/details/125896275