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

# 新版本

怎么用

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

怎么实现:

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
Last Updated: 1/13/2020, 7:38:12 AM
    asphyxia
    逆时针向