09-上下文

7/24/2023

# 一,上下文

# 1,什么是上下文

在React中,利用上下文,进行组件间的通信。类似于Vue中的proveder/inject。

特点:

  • 在组件树中,上下文中一种单向数据流通信,不能颠倒。
  • 通信是可以跨级的,祖先提供数据,后代消费数据。
  • 这个通过方法,不具有响应式。

创建对应的组件,如下:

1675305992924

浏览器中测试如下:

1675306004313

上下文是为了实现通信,需要创建一个上下文,如下:

1675306218888

使用上下文,有两种方案,方案1如下:

1675306302172

先在祖先中提供数据,如下 :

1675306382127

看Child能不能获取数据,如下:

1675306422809

上面是我们使用上下文的方式一,还有一种方式,是推荐的,如下:

1675306615651

总结使用上下文的步骤:

  • 第一步:创建const ThemeContent = React.createContext()创建上下文
  • 第二步:使用Provider提供数据,是给后代提供数据
  • 第三步:消费上下文中的数据有两种方案。

# 2,实现小案例

直接上代码如下:

import React, { PureComponent, useState } from "react";
const ThemeContext = React.createContext();
// Provider是用来提供数据
// Consumer是用来消费数据
const { Provider, Consumer } = ThemeContext

// 上下文只能类组件才有
class Child extends PureComponent {
    render() {
        console.log(this);
        return (
            <Consumer>
                {
                    (ctx) => {
                        return (
                            <div style={ctx}>
                                <h3>我是孩子组件</h3>
                            </div>
                        )
                    }
                }
            </Consumer>

        )
    }
}

function Parent(props) {
    return (
        <div>
            <h3>父组件</h3>
            <Child />
        </div>
    )
}

function PageA() {
    let obj = { a: 1 }
    // 在JSX中是不能直接渲染一个对象,但是可以渲染一个数组
    const [theme, setTheme] = useState({ color: "#000000", background: "#ffffff" })
    let change = (key, e) => {
        setTheme({ ...theme, [key]: e.target.value })
    }
    return (
        <Provider value={theme}>
            <div>
                <div>
                    <h2>页面</h2>
                    <hr />
                    <Parent />
                </div>
                <div>
                    前景色: <input type="color" value={theme.color} onChange={e => change('color', e)} />
                    背景色: <input type="color" value={theme.background} onChange={e => change('background', e)} />
                </div>
            </div>
        </Provider>
    )
}

export default PageA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

效果如下 :

1675308447941

把颜色切换,可以封装成一个组件,如下:

import React, { PureComponent, useState } from "react";
const ThemeContext = React.createContext();
// Provider是用来提供数据
// Consumer是用来消费数据
const { Provider, Consumer } = ThemeContext

// 上下文只能类组件才有
class Child extends PureComponent {
    render() {
        console.log(this);
        return (
            <Consumer>
                {
                    (ctx) => {
                        return (
                            <div style={ctx}>
                                <h3>我是孩子组件</h3>
                            </div>
                        )
                    }
                }
            </Consumer>

        )
    }
}

function Parent(props) {
    return (
        <div>
            <h3>父组件</h3>
            <Child />
        </div>
    )
}

function ThemeToggle({ theme, onChange }) {
    let change = (e) => {
        let key = e.target.name;
        let val = e.target.value;
        onChange({ ...theme, [key]: val })
    }
    return (
        <>
            <div>
                前景色: <input type="color" name="color" value={theme.color} onChange={change} />
                背景色: <input type="color" name="background" value={theme.background} onChange={change} />
            </div>
        </>
    )
}

function PageA() {
    let obj = { a: 1 }
    // 在JSX中是不能直接渲染一个对象,但是可以渲染一个数组
    const [theme, setTheme] = useState({ color: "#000000", background: "#ffffff" })
    let change = (key, e) => {
        setTheme({ ...theme, [key]: e.target.value })
    }
    return (
        <Provider value={theme}>
            <div>
                <div>
                    <h2>页面</h2>
                    <hr />
                    <Parent />
                </div>
                {/* onChange={e => setTheme(e)} 叫事件函数 */}
                <ThemeToggle theme={theme} onChange={e => setTheme(e)}></ThemeToggle>
            </div>
        </Provider>
    )
}

export default PageA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

效果如下:

1675308809341

上下文的使用场景:

  • 路由中会使用到上下文
  • 状态管理中也会使用到上下文
  • 在一些组件库,如切换主题,切换组件大小... 也会使用到上下文
  • 在际化中,也会使用到上文

总结一下React中的组件通信:

  • 状态提升(父传子,子传父),核心靠props
  • 上下文,是祖先与后代之间的通信,父子关系不需要明确
  • props穿透,需要搞清楚,父子关系,缺点:会让后代的props变得臃肿。
Last Updated: 2/2/2023, 5:44:28 PM