16.context-跨组件通信
2020-05-21 本文已影响0人
__疯子__
初始化组件
import React,{Component} from 'react'
import {render} from 'react-dom'
/**
* 展示具体内容组件
*/
class Counter extends Component{
render() {
return (
<span>
{0}
</span>
);
}
}
/**
* 按钮组件
*/
class CountBtn extends Component{
render() {
return (
<button>{this.props.children}</button>
);
}
}
/**
* 根组件
*/
class App extends Component{
render() {
return (
<>
<CountBtn type="decrement">-</CountBtn>
<Counter/>
<CountBtn type="increment">+</CountBtn>
</>
);
}
}
render(
<App/>,
document.getElementById("root")
);
跨组件通信
1.引用及解构
//createContext是react提供的一个用于跨组件传值的方法
import React,{Component,createContext} from 'react'
与render同级
// createContext这个方法的结果是一个对象,里面有Provider和Consumer
// Provider用于提供状态
// Consumer用于接收状态
const {
Provider,
Consumer:counterConsumer
}=createContext();
2.新写组件ConterProvider
class CounterProvider extends Component{
/**
* 构造函数
* @param props
*/
constructor(props) {
super(props);
//这里的状态是共享状态,任何CounterProvider的后代组件都可以通过CounterConsumer来接收这个值
this.state={
count:100,//count默认值为100
}
}
render() {
return (
// 属性value是默认属性名称
<Provider value={{
count:this.state.count
}}>
{this.props.children} {/* this.props.children = <App/>*/}
</Provider>
);
}
}
3.src/index.js
的render
函数
render(
<CounterProvider>
<App/>
</CounterProvider>,
document.getElementById("root")
);
4.将CounterProvider
中的state
属性进行展示
/**
* 展示具体内容组件
*/
class Counter extends Component {
render() {
/**
* CounterConsumer组件中只能是函数
* 参数value 是Provider的属性value中携带的值
*/
return (
<CounterConsumer>
{
(value) => {
return (
<span>
{value.count}
</span>
)
}
}
</CounterConsumer>
);
}
}
5.在CounterProvider
中添加修改state
属性的函数并以value
的形式向下传递
class CounterProvider extends Component {
/**
* 构造函数
* @param props
*/
constructor(props) {
super(props);
//CounterProvider私有的state
this.state = {
count: 100,//count默认值为100
}
}
// 减法
handleDecrement=()=>{
this.setState({
count:this.state.count-1
})
};
// 加法
handleIncrement=()=>{
this.setState({
count:this.state.count+1
})
};
render() {
return (
// 属性value是默认属性名称
// count handleDecrement handleIncrement 向下传递
<Provider value={{
count: this.state.count,
handleDecrement:this.handleDecrement,
handleIncrement:this.handleIncrement
}}>
{this.props.children} {/* this.props.children = <App/>*/}
</Provider>
);
}
}
6.在按钮点击的时候调用修改函数
/**
* 按钮组件
*/
class CountBtn extends Component {
render() {
return (
<CounterConsumer>
{
(value)=>{
const handleClick=this.props.type==="increment"?value.handleIncrement:value.handleDecrement
return (
<button onClick={handleClick}>{this.props.children}</button>
)
}
}
</CounterConsumer>
);
}
}
src/index.js
源码
//createContext是react提供的一个用于跨组件传值的方法
import React, {Component, createContext} from 'react'
import {render} from 'react-dom'
// createContext这个方法的结果是一个对象,里面有Provider和Consumer
// Provider用于提供状态
// Consumer用于接收状态
const {
Provider,
Consumer: CounterConsumer
} = createContext();
// 封装一个基本的Provider,如果直接使用Provider的话不方便管理状态
class CounterProvider extends Component {
/**
* 构造函数
* @param props
*/
constructor(props) {
super(props);
//这里的状态是共享状态,任何CounterProvider的后代组件都可以通过CounterConsumer来接收这个值
this.state = {
count: 100,//count默认值为100
}
}
// 减法
handleDecrement=()=>{
this.setState({
count:this.state.count-1
})
};
// 加法
handleIncrement=()=>{
this.setState({
count:this.state.count+1
})
};
render() {
return (
// 属性value是默认属性名称
// count handleDecrement handleIncrement 向下传递
<Provider value={{
count: this.state.count,
handleDecrement:this.handleDecrement,
handleIncrement:this.handleIncrement
}}>
{this.props.children} {/* this.props.children = <App/>*/}
</Provider>
);
}
}
/**
* 展示具体内容组件
*/
class Counter extends Component {
render() {
/**
* CounterConsumer组件中只能是函数
* 参数value 是Provider的属性value中携带的值
*/
return (
<CounterConsumer>
{
(value) => {
return (
<span>
{value.count}
</span>
)
}
}
</CounterConsumer>
);
}
}
/**
* 按钮组件
*/
class CountBtn extends Component {
render() {
return (
<CounterConsumer>
{
(value)=>{
const handleClick=this.props.type==="increment"?value.handleIncrement:value.handleDecrement;
return (
<button onClick={handleClick}>{this.props.children}</button>
)
}
}
</CounterConsumer>
);
}
}
/**
* 根组件
*/
class App extends Component {
render() {
return (
<>
<CountBtn type="decrement">-</CountBtn>
<Counter/>
<CountBtn type="increment">+</CountBtn>
</>
);
}
}
render(
<CounterProvider>
<App/>
</CounterProvider>,
document.getElementById("root")
);
流程解释
1.创建createContext
2.根据createContext
进行解构
-
createContext
这个方法的结果是一个对象,里面有Provider
和Consumer
-
Provider
用于提供状态 -
Consumer
用于接收状态
最终解构出两个组件
1.`Provider` #用于提供状态
2.`CounterConsumer` #用于接收状态
3.封装一个基本的Provider
组件名称命名为CounterProvider
,如果直接使用Provider
的话不方便管理状态
在
CounterProvider
组件中需要返回一个Provider
以及{this.props.children}
这个children
相当于Vue
中的<slot/>
组件
4.在index.js
的render
函数中以CounterProvider
组件为父组件App
组件为子组件
5.在App
组件中再去调用CountBtn
和Counter
组件
6.在CountBtn
组件中使用CounterConsumer
进行接收CounterProvider
组件传递的value
属性的值
7.在Counter
组件中使用CounterConsumer
进行接收CounterProvider
组件传递的value
属性的值
context-跨组件完