美文网首页
16.context-跨组件通信

16.context-跨组件通信

作者: __疯子__ | 来源:发表于2020-05-21 17:38 被阅读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进行解构

    • createContext这个方法的结果是一个对象,里面有ProviderConsumer
    • Provider用于提供状态
    • Consumer用于接收状态
    最终解构出两个组件
    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-跨组件

    相关文章

      网友评论

          本文标题:16.context-跨组件通信

          本文链接:https://www.haomeiwen.com/subject/vmxtahtx.html