实际项目中使用 react context 实现计数器功能

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}

猜你喜欢

转载自blog.csdn.net/Charissa2017/article/details/105761915