React知识整理-上下文Context
冰洋 1/12/2020 React
react从入门到放弃
案例展示:
# 旧版本
import React, { Component } from 'react'
import PropTypes from 'prop-types';
/**
* Header:头部包含标题Title
**/
class Header extends Component {
//定义子上下文对象的属性和类型
static childContextTypes = {
name: PropTypes.string,
age: PropTypes.number
}
//返回或者说定义真正的子上下文
getChildContext() {
return {
age: 10,
name: 'Header'
}
}
render() {
console.log(this.context)
return <div style={{ border: '5px solid green', padding: '5px' }}>
<Title/>
</div>
}
}
// 标题
class Title extends Component {
//表示或者 说指定我要获取哪些上下文对象
static contextTypes = {
color: PropTypes.string,
name: PropTypes.string,
age: PropTypes.number
}
render() {
console.log(this.context)
return <div style={{ border: '5px solid orange', padding: '5px', color: this.context.color }}>
Title
</div>
}
}
/**
* Main:主体,包含Content内容
**/
class Main extends Component {
render() {
return <div style={{ border: '5px solid blue', padding: '5px' }}>
<h2>Main</h2>
<Content></Content>
</div>
}
}
// 内容
class Content extends Component {
static contextTypes = {
color: PropTypes.string,
name: PropTypes.string,
age: PropTypes.number,
setColor: PropTypes.func
}
render() {
return <div style={{ border: '5px solid pink', padding: '5px', color: this.context.color }}>
Content
<button onClick={() => this.context.setColor('red')}>变红</button>
<button onClick={() => this.context.setColor('green')}>变绿</button>
</div>
}
}
/**
* Page页面主体
**/
export default class Page extends Component {
constructor() {
super();
this.state = { color: 'gray' };
}
//定义子上下文对象的属性和类型
static childContextTypes = {
name: PropTypes.string,
color: PropTypes.string,
setColor: PropTypes.func
}
//返回或者说定义真正的子上下文
getChildContext() {
return {
color: this.state.color,
setColor: this.setColor,
name: 'Page'
}
}
setColor = (color) => {
this.setState({ color });
}
render() {
return (
<div style={{ border: '5px solid red', padding: '5px' }}>
Page
<Header><Title/></Header>
<Main><Content/></Main>
</div>
)
}
}
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# 新版本
怎么用
import React, { Component } from 'react'
const ThemeContext = React.createContext();
/**
* Header:头部包含标题Title
**/
class Header extends Component {
render() {
console.log(this.context)
return <div style={{ border: '5px solid green', padding: '5px' }}>
<Title/>
<Title1/>
</div>
}
}
// 头部标题 类组件
class Title extends Component {
static contextType = ThemeContext
render() {
this.context = Title.contextType.Provider.value;
console.log(this.context)
return <div style={{ border: '5px solid orange', padding: '5px', color: this.context.color }}>
类组件:Title
</div>
}
}
// 头部标题 函数组件
function Title1 (props){
return (
<ThemeContext.Consumer>
{
value=>(
<div style={{ border: '5px solid orange', padding: '5px', color: value.color }}>
函数组件Title
</div>
)
}
</ThemeContext.Consumer>
)
}
/**
* 主体: 包含Content内容
**/
class Main extends Component {
render() {
return <div style={{ border: '5px solid blue', padding: '5px' }}>
Main
<Content/>
<Content1/>
</div>
}
}
// 内容 Content 类组件
class Content extends Component {
static contextType = ThemeContext
render() {
this.context = Content.contextType.Provider.value;
return <div style={{ border: '5px solid pink', padding: '5px', color: this.context.color }}>
类组件:Content
<button onClick={() => this.context.setColor('red')}>变红</button>
<button onClick={() => this.context.setColor('green')}>变绿</button>
</div>
}
}
// 内容Content1 函数组件
function Content1(){
return (
<ThemeContext.Consumer>
{
value=>(
<div style={{ border: '5px solid pink', padding: '5px', color: value.color }}>
函数组件:Content1
<button onClick={() => value.setColor('red')}>变红</button>
<button onClick={() => value.setColor('green')}>变绿</button>
</div>
)
}
</ThemeContext.Consumer>
)
}
/**
* Page页面主体
**/
export default class Page extends Component {
constructor() {
super();
this.state = { color: 'red' };
}
setColor = (color) => {
this.setState({ color });
}
render() {
let ctx = {color:this.state.color,setColor:this.setColor};
return (
<ThemeContext.Provider value={ctx}>
<div style={{ border: '5px solid red', padding: '5px' }}>
Page
<Header><Title/></Header>
<Main><Content/></Main>
</div>
</ThemeContext.Provider>
)
}
}
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
怎么实现:
import React, { Component } from 'react'
//const ThemeContext = React.createContext();
const ThemeContext = createContext();
// 欺骗React引入的是原生的createContext。
const REACT_CONTEXT_TYPE = Symbol.for('react.context') ;
const REACT_PROVIDER_TYPE = Symbol.for('react.provider');
function createContext(){
class Provider extends Component{
static value;
$$typeof=REACT_PROVIDER_TYPE
constructor(props){
super(props);
Provider.value = props.value;
this.state = {value:props.value}
}
static getDerivedStateFromProps(props, state) {
// 通过props更新state
Provider.value = props.value;
return {value:props.props};
}
render(){
return this.props.children;
}
}
class Consumer extends Component{
render(){
// 渲染子组件 并将Provider属性传入
return this.props.children(Provider.value);
}
}
return {$$typeof: REACT_CONTEXT_TYPE,Provider,Consumer}
}
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
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