16.context-跨组件通信

2020-05-21  本文已影响0人  __疯子__

初始化组件

import React,{Component} from 'react'
import {render} from 'react-dom'

/**
 * 展示具体内容组件
 */
class Counter extends Component{
    render() {
        return (
            <span>
                {0}
            </span>
        );
    }
}

/**
 * 按钮组件
 */
class CountBtn extends Component{
    render() {
        return (
            <button>{this.props.children}</button>
        );
    }
}

/**
 * 根组件
 */
class App extends Component{
    render() {
        return (
            <>
                <CountBtn type="decrement">-</CountBtn>
                <Counter/>
                <CountBtn type="increment">+</CountBtn>
            </>
        );
    }
}

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

跨组件通信

1.引用及解构

//createContext是react提供的一个用于跨组件传值的方法
import React,{Component,createContext} from 'react'

与render同级

// createContext这个方法的结果是一个对象,里面有Provider和Consumer
// Provider用于提供状态
// Consumer用于接收状态
const {
    Provider,
    Consumer:counterConsumer 
}=createContext();

2.新写组件ConterProvider

class CounterProvider extends Component{
    /**
     * 构造函数
     * @param props
     */
    constructor(props) {
        super(props);
        //这里的状态是共享状态,任何CounterProvider的后代组件都可以通过CounterConsumer来接收这个值
        this.state={
            count:100,//count默认值为100
        }
    }

    render() {
        return (
            // 属性value是默认属性名称
            <Provider value={{
                count:this.state.count
            }}>
                {this.props.children} {/* this.props.children = <App/>*/}
            </Provider>
        );
    }
}

3.src/index.jsrender函数

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

4.将CounterProvider中的state属性进行展示

/**
 * 展示具体内容组件
 */
class Counter extends Component {
    render() {
        /**
         * CounterConsumer组件中只能是函数
         * 参数value 是Provider的属性value中携带的值
         */
        return (
            <CounterConsumer>
                {
                    (value) => {
                        return (
                            <span>
                                {value.count}
                            </span>
                        )
                    }
                }
            </CounterConsumer>
        );
    }
}

5.在CounterProvider中添加修改state属性的函数并以value的形式向下传递

class CounterProvider extends Component {
    /**
     * 构造函数
     * @param props
     */
    constructor(props) {
        super(props);
        //CounterProvider私有的state
        this.state = {
            count: 100,//count默认值为100
        }
    }
    // 减法
    handleDecrement=()=>{
        this.setState({
            count:this.state.count-1
        })
    };
    // 加法
    handleIncrement=()=>{
        this.setState({
            count:this.state.count+1
        })
    };

    render() {
        return (
            // 属性value是默认属性名称
            // count handleDecrement handleIncrement 向下传递
            <Provider value={{
                count: this.state.count,
                handleDecrement:this.handleDecrement,
                handleIncrement:this.handleIncrement
            }}>
                {this.props.children} {/* this.props.children = <App/>*/}
            </Provider>
        );
    }
}

6.在按钮点击的时候调用修改函数

/**
 * 按钮组件
 */
class CountBtn extends Component {
    render() {
        return (
            <CounterConsumer>
                {
                    (value)=>{
                        const handleClick=this.props.type==="increment"?value.handleIncrement:value.handleDecrement
                        return (
                            <button onClick={handleClick}>{this.props.children}</button>
                        )
                    }
                }
            </CounterConsumer>
        );
    }
}

src/index.js源码

//createContext是react提供的一个用于跨组件传值的方法
import React, {Component, createContext} from 'react'
import {render} from 'react-dom'

// createContext这个方法的结果是一个对象,里面有Provider和Consumer
// Provider用于提供状态
// Consumer用于接收状态
const {
    Provider,
    Consumer: CounterConsumer
} = createContext();

// 封装一个基本的Provider,如果直接使用Provider的话不方便管理状态
class CounterProvider extends Component {
    /**
     * 构造函数
     * @param props
     */
    constructor(props) {
        super(props);
        //这里的状态是共享状态,任何CounterProvider的后代组件都可以通过CounterConsumer来接收这个值
        this.state = {
            count: 100,//count默认值为100
        }
    }
    // 减法
    handleDecrement=()=>{
        this.setState({
            count:this.state.count-1
        })
    };
    // 加法
    handleIncrement=()=>{
        this.setState({
            count:this.state.count+1
        })
    };

    render() {
        return (
            // 属性value是默认属性名称
            // count handleDecrement handleIncrement 向下传递
            <Provider value={{
                count: this.state.count,
                handleDecrement:this.handleDecrement,
                handleIncrement:this.handleIncrement
            }}>
                {this.props.children} {/* this.props.children = <App/>*/}
            </Provider>
        );
    }
}


/**
 * 展示具体内容组件
 */
class Counter extends Component {
    render() {
        /**
         * CounterConsumer组件中只能是函数
         * 参数value 是Provider的属性value中携带的值
         */
        return (
            <CounterConsumer>
                {
                    (value) => {
                        return (
                            <span>
                                {value.count}
                            </span>
                        )
                    }
                }
            </CounterConsumer>
        );
    }
}

/**
 * 按钮组件
 */
class CountBtn extends Component {
    render() {
        return (
            <CounterConsumer>
                {
                    (value)=>{
                        const handleClick=this.props.type==="increment"?value.handleIncrement:value.handleDecrement;
                        return (
                            <button onClick={handleClick}>{this.props.children}</button>
                        )
                    }
                }
            </CounterConsumer>
        );
    }
}

/**
 * 根组件
 */
class App extends Component {

    render() {
        return (
            <>
                <CountBtn type="decrement">-</CountBtn>
                <Counter/>
                <CountBtn type="increment">+</CountBtn>
            </>
        );
    }
}

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

流程解释

1.创建createContext
2.根据createContext进行解构

最终解构出两个组件
1.`Provider` #用于提供状态
2.`CounterConsumer` #用于接收状态

3.封装一个基本的Provider组件名称命名为CounterProvider,如果直接使用Provider的话不方便管理状态

CounterProvider组件中需要返回一个Provider以及{this.props.children}这个children相当于Vue中的<slot/>组件

4.在index.jsrender函数中以CounterProvider组件为父组件App组件为子组件
5.在App组件中再去调用CountBtnCounter组件
6.在CountBtn组件中使用CounterConsumer进行接收CounterProvider组件传递的value属性的值
7.在Counter组件中使用CounterConsumer进行接收CounterProvider组件传递的value属性的值


context-跨组件

上一篇下一篇

猜你喜欢

热点阅读