09-上下文
码路教育 7/24/2023
# 一,上下文
# 1,什么是上下文
在React中,利用上下文,进行组件间的通信。类似于Vue中的proveder/inject。
特点:
- 在组件树中,上下文中一种单向数据流通信,不能颠倒。
- 通信是可以跨级的,祖先提供数据,后代消费数据。
- 这个通过方法,不具有响应式。
创建对应的组件,如下:
浏览器中测试如下:
上下文是为了实现通信,需要创建一个上下文,如下:
使用上下文,有两种方案,方案1如下:
先在祖先中提供数据,如下 :
看Child能不能获取数据,如下:
上面是我们使用上下文的方式一,还有一种方式,是推荐的,如下:
总结使用上下文的步骤:
- 第一步:创建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
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
效果如下 :
把颜色切换,可以封装成一个组件,如下:
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
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
效果如下:
上下文的使用场景:
- 路由中会使用到上下文
- 状态管理中也会使用到上下文
- 在一些组件库,如切换主题,切换组件大小... 也会使用到上下文
- 在际化中,也会使用到上文
总结一下React中的组件通信:
- 状态提升(父传子,子传父),核心靠props
- 上下文,是祖先与后代之间的通信,父子关系不需要明确
- props穿透,需要搞清楚,父子关系,缺点:会让后代的props变得臃肿。