React组件化-02-组件间通信Context

727 阅读2分钟

1.React的Context

Context 提供了⼀个⽆需为每层组件⼿动添加 props,就能在 组件树 间进⾏数据传递的⽅法。

Context的使用场景:

Context设计的⽬的是为了共享那些 全局 的数据,例如当前认证的⽤户、主题等。

🚀 下面是通过第①种渲染方式改变按钮主题的例子👇:

  1. 通过 React.createContext() 创建一个context 并赋值给变量ThemeContext
  2. ThemeContext 组件中使用ThemeContext.Provider进行包裹,并添加value属性将值传出去
  3. Context的ThemeContext.Provider ----→ ToolBar ----→ ThemeBtn
  4. ThemeBtn中如果是通过 this.context使用value的值 的话,那么在组件中 必须定义一个static自定义属性承载创建的ThemeContext
  5. 组件中使用 this.context 渲染即可

🚀 此种渲染方式: 定制当前创建的 上下文对象,为当前实例的 static静态属性

import React, {Component} from 'react';
import {Button} from "antd";

const ThemeContext = React.createContext();

class Context extends Component {
    constructor(props) {
        super(props);
        this.state = {
            store :{
                type:"primary",
                name:"按钮"
            }
        }
    }
    render() {
        return (
            <ThemeContext.Provider value = {this.state.store}>
                <Toolbar> </Toolbar>
            </ThemeContext.Provider>
        );
    }
}
export default Context;

function Toolbar(props){
    return <ThemeBtn> </ThemeBtn>
}

//按钮Btn
class ThemeBtn extends Component {
    constructor(props) {
        super(props);
        // 🚀 this有个叫context的属性,如果Provider中挂载了value值,那么this.context就会拿到这个值
        console.log(this);
    }
    // 🚀 如果在组件中想要使用this.context必须先定义一个static静态属性值
    static contextType = ThemeContext;
    render() {
        return (
            <Button type={this.context}>初始化按钮</Button>
        );
    }
}

🚀 下面是通过第②种渲染方式改变按钮主题的例子👇:

  1. 前3步,步骤骤和 第①种一样,第4步的时候是使用的 ThemeContext.Consumer 对渲染出口的内容进行包裹。
  2. ThemeContext.Consumer内部使用通过一个 箭头函数去接收 ThemeContext.Provider提供的 value属性,返回一个jsx , 然后在页面上完成渲染。
import React, {Component} from 'react';
import {Button} from "antd";

const ThemeContext = React.createContext();
class ThemeBtn extends Component {
    constructor(props) {
        super(props);
        // 🚀 this有个叫context的属性,如果Provider中挂载了value值,那么this.context就会拿到这个值
        console.log(this);
    }
    render() {
        return (
            <ThemeContext.Consumer>
                {
                    (value)=>{
                        return (
                            <Button type={value.type}>初始化按钮</Button>
                        )
                    }
                }
            </ThemeContext.Consumer>
        );
    }
}

function Toolbar(props){
    return <ThemeBtn> </ThemeBtn>
}

class Context extends Component {
    constructor(props) {
        super(props);
        this.state = {
            store :{
                type:"primary",
                name:"按钮"
            }
        }
    }
    render() {
        return (
            <ThemeContext.Provider value = {this.state.store}>
                <Toolbar> </Toolbar>
            </ThemeContext.Provider>
        );
    }
}

export default Context;

2.组件通信高组件装饰器写法:

将公用的部分抽出去,完成复用,从而完成对代码的瘦身减脂~!

下面是改造后的代码:

  1. 使用了高阶组件,抽离了公用的部分;
  2. withProvider 为提供者; withConsumer为消费者
  3. {...this.props} 就是保留原有的 props
// 🌵index.js

import React,{Component} from "react";
const ThemeContext = React.createContext();

// 🚀 提供者
export const withProvider = Comp => {
    return class extends Component{
        constructor(props) {
            super(props);
            //共享的数据
            this.state = {
                store :{
                    type:"primary",
                    name:"按钮"
                }
            }
        }
        render() {
            return(
               <ThemeContext.Provider value={this.state.store}>
                   <Comp {...this.props}> </Comp>
               </ThemeContext.Provider>
            )
        }
    }
}
// 🚀 消费者
export const withConsumer  = Comp => {
    return class extends Component{
        render() {
            return (
                <ThemeContext.Consumer>
                    {
                        (value)=>{
                            return (
                                //🚀 这里将value作为Comp的props传递下去
                                <Comp value = {value}> </Comp>
                            )
                        }
                    }
                </ThemeContext.Consumer>
            )
        }
    }
}
// 🌵Conetxt.js

import React, {Component} from 'react';
import {Button} from "antd";
import {withProvider,withConsumer} from "../HOC";

//🚀 消费者装饰器
@withConsumer
class ThemeBtn extends Component {
    constructor(props) {
        super(props);
    }
    render() {
        // 🚀 这里通过this.props来接收
        return <Button type={this.props.value.type}>装饰器初始化按钮</Button>
    }
}

function Toolbar(props){
    return <ThemeBtn> </ThemeBtn>
}
// 🚀 提供者装饰器
@withProvider
class Context extends Component {
    render() {
        return <Toolbar> </Toolbar>
    }
}

export default Context;