react 中跨组件通信,可以通过 context 方式,这篇文章主要讲的是在实际项目中,怎样通过 context 来实现计数器的功能。
最终实现的效果:点击右边的加号按钮,中间的数字加1;点击左边的减号按钮,中间的数字减1;
目录结构:
├── index.jsx //入口文件
├── Count.jsx //显示中间数字的组件
├── CountButton.jsx //显示按钮的组件
├── CounterContext.jsx //context 组件,用来操作数据
index.jsx入口文件:
- CounterProvider 是对 createContext().Provider 的二次封装;
- 增、减的按钮使用的是同一个组件,通过属性传值来判断是增还是减;
- 在最外层包裹 <CounterProvider>,其内部的所有子组件都可以接收到 CounterProvider 的 value 值;
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import Count from './Count'
import CountButton from './CountButton'
import {CounterProvider} from './CounterContext'
class Cart extends Component {
render() {
return (
//CounterProvider是对createContext().Provider的二次封装
<CounterProvider>
<CountButton type="decrement"></CountButton>
<Count></Count>
<CountButton type="increment"></CountButton>
</CounterProvider>
)
}
}
ReactDOM.render(
<Cart/>,
document.getElementById('root')
);
Count.jsx文件:
- 读取 CounterProvider 的属性 value 中的 count 值;
- 用来展示中间的数字,只有读取的功能,不对数据做操作;
import React from 'react'
import {CountConsumer} from './CounterContext'
const Count=()=>{
return(
<CountConsumer>
{
({count})=>{
return <span>{count}</span>
}
}
</CountConsumer>
)
}
export default Count;
CountButton.jsx文件:
- 读取 CounterProvider 属性 value 中的 incrementCount 和 decrementCount;
- 用来展示增加、减小的两个按钮,通过属性值确定按钮的展示内容,和点击按钮触发的事件;
- 触发事件调用 context 中的方法,在这里不直接对数据做操作;
import React from 'react'
import{CountConsumer} from './CounterContext'
const CountButton = (props)=>{
return(
<CountConsumer>
{
({incrementCount,decrementCount})=>{
let {type}=props;
let btnTxt=type==="increment"?"+":"-";
let handleClick=type==="increment"?incrementCount:decrementCount
return <button onClick={handleClick}>{btnTxt}</button>
}
}
</CountConsumer>
)
}
export default CountButton;
CounterContext.jsx文件:
- 对 createContext() 中的 Provider 方法做二次封装,将要传递的数据和方法添加到 value 属性上;
- 所有对数据做处理的操作都在这个文件里执行;
- 最后导出的是 CounterProvider (封装后的Provider) 和 CountConsumer(就是Consumer);
import React, { Component ,createContext} from 'react'
//解构出createContext()的两个方法
const {Provider,Consumer:CountConsumer}=createContext();
//CounterProvider这个类组件是把 Provider重新做了封装
class CounterProvider extends Component {
constructor(){
super();
this.state={
count:1
}
}
//增加
incrementCount=()=>{
this.setState((preState)=>{
return{
count:preState.count+1
}
})
}
//减少
decrementCount=()=>{
this.setState((preState)=>{
return{
count:preState.count-1
}
})
}
render() {
return (
<Provider value={{
count:this.state.count,
incrementCount:this.incrementCount,
decrementCount:this.decrementCount
}}>
{
//表示标签内所有的后代组件都可以读取到value值
this.props.children
}
</Provider>
)
}
}
export {CounterProvider,CountConsumer}