react4.0——render-props、高阶组件

React4.0

render-props和高阶组件

render-props

两个组件中的部分功能相似或相同,可以复用相似的功能(联想函数封装),

复用什么?1.state,2.操作state的方法(组件状态逻辑)

两种方式:1.render props模式;2.高阶组件(HOC)

这两种方式不是API,而是利用React自身特点的编码技巧,演化而成的固定模式(写法)

获取到该组件中复用的state:在使用组件时,添加一个值为函数的prop,通过函数参数来获取(需要组件内部实现)

//render属性的值是一个函数,参数prop是复用的state
<Mouse render={(props)=>{}}

渲染任意的UI:使用该函数的返回值作为要渲染的UI内容(需要组件内部实现)

<Mouse render={(props)=>{
<p>复用的state:{props.name}</p>
}}
步骤:

1.创建要复用的组件(Mouse),在组件中提供复用的状态逻辑代码(1.状态,2.操作状态的方法)

2.将要复用的状态(state)作为props.render(state)方法的参数,暴露到组件外部

3.使用props.render()的返回值作为要渲染的内容

Mouse组件负责:封装复用的状态逻辑代码(1.状态,2.操作状态的方法)

状态:state={x:0,y:0}

操作状态的方法:handle

传入的render prop负责:使用复用的状态来渲染UI结构

import React from 'react';
import ReactDOM from 'react-dom';
import img from "./img/success.png"

// 复用状态,复用函数
class Mouse extends React.Component {
    // 状态
    state = {
        x: 0,
        y: 0
    }
    // 监听鼠标移动
    componentDidMount() {
        window.addEventListener("mousemove", this.handle)
    }
    // 监听的事件
    handle = e => {
        this.setState({
            x: e.clientX,
            y: e.clientY
        })
    }
    render() {
        return (
            this.props.render(this.state)
        )
    }
}

// 使用同一个组件,不同之处在return的内容不同
// mouse就是一个对象,就是Mouse组件的状态state
class App extends React.Component {
    render() {
        return (
            <div>
                <p>render props模式</p>
                <Mouse render={mouse => {
                    return (
                        <p>鼠标的位置:{mouse.x},{mouse.y}</p>
                    )
                }} />
                {/* img标签要加alt属性,否则报错 */}
                <Mouse render={(mouse) => {
                    return (
                        <img src={img} style={{ position: 'absolute', top: mouse.y, left: mouse.x }} alt="pic" />
                    )
                }} />
            </div>
        )
    }
}

ReactDOM.render(
    <div><App /></div>,
    document.getElementById('root')
);
代码优化

1.推荐:给render props 模式添加props效验

2.应该在组件卸载时解除mousemove事件绑定

import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types'
// 导入图片资源
import img from "./img/success.png"
// 复用组件:鼠标位置复用
class Mouse extends React.Component {
    // 鼠标位置状态
    state = {
        x: 0,
        y: 0
    }
    // 监听鼠标移动事件
    componentDidMount() {
        window.addEventListener("mousemove", this.handle)
    }
    // 鼠标移动事件的处理
    handle = e => {
        this.setState({
            x: e.clientX,
            y: e.clientY
        })
    }
    render() {
        return (
            // this.props.render(this.state)
            //children属性代替render助兴
            this.props.children(this.state)
        )
    }
    // 优化推荐:组件卸载时移除监听鼠标移动事件
    componentWillUnmount() {
        window.removeEventListener("mousemove", this.handle)
    }
}

// 优化:添加props效验
// propTypes首字母是小写的,不是导入的PropTypes
Mouse.propTypes = {
    // Mouse标签的子节点是一个函数,必要的
    children:PropTypes.func.isRequired
}

// 使用同一个组件,不同之处在return的内容不同
// mouse就是一个对象,就是Mouse组件的状态state
class App extends React.Component {
    render() {
        return (
            <div>
                <p>render props模式</p>
                {/* <Mouse render={mouse => {
                    return (
                        <p>鼠标的位置:{mouse.x},{mouse.y}</p>
                    )
                }} /> */}
                {/* img标签要加alt属性,否则报错 */}
                {/* <Mouse render={(mouse) => {
                    return (
                        <img src={img} style={{ position: 'absolute', top: mouse.y, left: mouse.x }} alt="pic" />
                    )
                }} /> */}
                <Mouse>
                    {mouse => {
                        return (
                            <p>鼠标的位置:{mouse.x},{mouse.y}</p>
                        )
                    }}
                </Mouse>
                <Mouse>
                    {mouse => {
                        return (
                            <img src={img} style={{ position: "absolute", top: mouse.y, left: mouse.x }} alt='pic' />
                        )
                    }}
                </Mouse>
            </div>
        )
    }
}

ReactDOM.render(
    <div><App /></div>,
    document.getElementById('root')
);
高阶组件

目的:实现状态逻辑复用,采用包装(装饰)模式

高阶组件就相当于手机壳,通过包装组件,增强组件功能

**高阶组件(HOC,Higher-Order Component)**是一个函数,接收要包装的组件,返回增强后的组件

高阶组件创建一个类组件,在这个类组件中提供复用的状态逻辑代码,通过prop将复用的状态传递给被包装组件

:用于解构

import React from 'react';
import ReactDOM from 'react-dom';
// import PropTypes from 'prop-types'
// 导入图片资源
import img from "./img/success.png"

// 1.高阶组件:是一个函数,函数名用with开头
// 参数是一个组件
function withMouse(Wrapped) {
    // 创建组件(复用)
    class Mouse extends React.Component {
        // 状态
        state = {
            x: 0,
            y: 0
        }
        // 挂载阶段
        componentDidMount() {
            // 鼠标移动了,就触发this.handle
            window.addEventListener("mousemove", this.handle)
        }
        // 渲染
        // 返回的是高阶组件函数的参数,参数就是一个组件
        render() {
            return (
                // ...this.state:解构this.state
                <Wrapped {...this.state} />
            )
        }
        // 处理函数
        handle = (e) => {
            this.setState({
                x: e.clientX,
                y: e.clientY
            })
        }
        // 卸载阶段
        componentWillUnmount() {
            window.removeEventListener("mousemove", this.handle)
        }
    }
    // 返回组件
    return Mouse
}
// 2.需要增强的组件
const Posi = props => {
    return (
        <p>x:{props.x},y:{props.y}</p>
    )
}
// 需要增强的组件
const Icon = props => {
    return (
        <img src={img} style={{ position: 'absolute', top: props.y, left:props.x }} alt='icon' />
    )
}
// 通过增强后的组件
const MousePosi = withMouse(Posi)
const MouseIcon = withMouse(Icon)

class App extends React.Component {
    render() {
        return (
            <div>
                {/* 这里显示的都是通过高阶组件增强后的组件 */}
                <MousePosi />
                <MouseIcon />
            </div>
        )
    }
}

ReactDOM.render(
    <div><App /></div>,
    document.getElementById('root')
);
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值