React-跨组件通讯-context

在之前的通讯代码当中,发现一个问题,如果传递数据层次太深, 一层一层的传递比较麻烦, 所以 React 也提供了其它的解决方案:

  • 通过 context 上下文传递
  • 通过 Redux 传递 (相当于 Vuex)
  • 通过 Hooks 传递 (相当牛X)

通过 context 上下文传递数据

调用创建上下文的方法, 只要我们调用了创建上下文的方法, 这个方法就会给我们返回两个容器组件,生产者容器组件(Provider) / 消费者容器组件(Consumer),只要拿到了这两个容器组件, 那么我们就可以通过这两个容器组件从祖先传递数据给所有的后代了,首先在祖先组件中利用 '生产者容器组件' 包裹后代组件,然后在后代组件中利用 '消费者容器组件' 获取祖先组件传递过来的数据即可,接下来就是代码实现案例。

  1. 创建一个上下文对象
const AppContext = React.createContext({});
  1. 从上下文对象中获取容器组件
    1. Provider: 生产者容器组件, 专门用于负责生产数据
    2. Consumer: 消费者容器组件, 专门用于消费生产者容器组件生产的数据的
    3. 容器组件: 专门用于包裹其它组件的组件, 我们就称之为容器组件
const {Provider, Consumer} = AppContext;

我们可以在生产者容器组件中通过 value 来生产数据:

import React from 'react';
import './App.css';

const AppContext = React.createContext({});
const {Provider, Consumer} = AppContext;
class Son extends React.Component {
    render() {
        return (
            <Consumer>
                {
                    (value) => {
                        return (
                            <div>
                                <p>{value.name}</p>
                                <p>{value.age}</p>
                            </div>
                        )
                    }
                }
            </Consumer>
        );
    }
}

class Father extends React.Component {
    render() {
        return (
            <div>
                <Son/>
            </div>
        );
    }
}

class App extends React.Component {
    render() {
        return (
            <Provider value={{name: 'BNTang', age: 18}}>
                <Father/>
            </Provider>
        )
    }
}

export default App;

image-20220413201718507

第二种方式传递数据

也是利用 context 上下文进行传递,只不过使用的方式不同,我不知道你们有没有发现在创建上下文对象的时候,当中有一个参数,那么第二种方式就是在于这个参数当中,将我们需要传递的数据写在这个参数当中,然后我们在需要使用的组件利用 组件.contextType = 上下文对象, 然后在使用的组件当中直接使用 this.context.数据 这样即可进行使用。

import React from 'react';
import './App.css';

const AppContext = React.createContext({
    name: 'BNTang',
    age: 18
});

class Son extends React.Component {
    render() {
        return (
            <div>
                <p>{this.context.name}</p>
                <p>{this.context.age}</p>
            </div>
        )
    }
}

Son.contextType = AppContext;

class Father extends React.Component {
    render() {
        return (
            <div>
                <Son/>
            </div>
        );
    }
}

class App extends React.Component {
    render() {
        return (
            <div>
                <Father/>
            </div>
        )
    }
}

export default App;

多个生产者与多个消费者

在这种模式下,是无法使用我们的第二种方式进行消费数据的,因为 contextType 是一个属性,后面编写的会覆盖前面的,所以使用不了,那么就来看一个多个生产者与多个消费者的用法吧:

import React from 'react';
import './App.css';

// 创建上下文对象
const AppContext1 = React.createContext({});
const AppContext2 = React.createContext({});

class Son extends React.Component {
    render() {
        return (
            <AppContext1.Consumer>
                {
                    (value1) => {
                        return (
                            <AppContext2.Consumer>
                                {
                                    (value2) => {
                                        return (
                                            <div>
                                                <p>{value1.name}</p>
                                                <p>{value2.age}</p>
                                            </div>
                                        )
                                    }
                                }
                            </AppContext2.Consumer>
                        )
                    }
                }
            </AppContext1.Consumer>
        )
    }
}

class Father extends React.Component {
    render() {
        return (
            <div>
                <Son/>
            </div>
        );
    }
}

class App extends React.Component {
    render() {
        return (
            // 生产者1
            <AppContext1.Provider value={{name: 'BNTang666'}}>

                {/*
                生产者2
                */}
                <AppContext2.Provider value={{age: 18}}>
                    <Father/>
                </AppContext2.Provider>
            </AppContext1.Provider>
        )
    }
}

export default App;
posted @ 2022-04-14 11:00  BNTang  阅读(125)  评论(0编辑  收藏  举报