React入门(四)

组件通信


复合组件:父组件嵌套子组件

方案一:属性传递(适用于父与子)

       调取子组件的时候,把信息基于属性的方式传递给子组件(子组件props中存储传递的信息),这种方式只能是父组件把信息传递子组件,子组件无法直接地把信息传递给父组件,也就是说属性传递信息是单向传递的。不过利用回调函数机制也可以实现子改父的效果,即父组件把一个函数通过属性或者上下文的方式传递给子组件,子组件中只要把这个方法执行即可

/*HEAD*/
class Head extends React.Component {
    render() {
        return 

{/*子组件通过属性获取父组件传递的状态*/} 点击次数:{this.props.count}

; } } /*BODY*/ class Body extends React.Component { render() { return
; } } /*PANEL*/ class Panel extends React.Component { constructor() { super(); this.state = {n: 0}; } fn = () => { // 修改PANEL的状态信息 this.setState({ n: this.state.n + 1 }); }; render() { return
{/*父组件中在调取子组件的时候,把信息通过属性传递给子组件*/} {/*父组件把自己的一个方法基于属性传递给子组件,目的是在子组件中执行这个方法*/}
; } }
效果演示

方案二:发布订阅方式

1.调用父组件创建一个属于自己的事件池
2.在子组件中把修改本身状态的方法放到事件池中
3.在点击按钮的时候,通知事件池中的方法执行即可

方案三:基于上下文进行传递

       父组件先把需要给后代元素(包括孙子元素)使用的信息都设置好(设置在上下文中),后代组件需要用到父组件中的信息,主动去父组件中调取使用即可

  • 方法一
    1.父组件设置childContextTypesgetChildContext
    2.子组件通过contextTypes获取上下文
    // 父组件设置信息
    static childContextTypes = {
        // 设置上下文中信息值的类型,需借助prop-types
        n: PropTypes.number,
        m: PropTypes.number
    };
    getChildContext() {
        // RETURN的是啥,相当相当于往上下文中放了啥
        let {count: {n = 0, m = 0}} = this.props;
        return {
            n,
            m
        };
    }
    
    // 子组件主动获取需要的信息
    static contextTypes = {
        // 首先类型需要和设置时类型一致,否则报错;然后根据需求提取上下文的内容即可
        n: PropTypes.number,
        m: PropTypes.number
    };
    
  • 方法二
    1.React.createContext()创建上下文
    2.通过ThemeContext.ProviderThemeContext.Consumer标签进行信息传递

属性传递 VS 上下文传递

1.接收值的方式:属性传递时子组件通过props被动接收传递的值,而上下文传递时子组件是主动通过contextTypes挑选自己需要的值
2.值的可修改性:属性传递中父传子的属性属于只读属性,不可修改,最多只能通过defaultProps设置未传时的默认值,而上下文传递时子组件是可以修改获取到的上下文信息的(但是不会影响到父组件中的信息,其它组件不受影响)
3.后代接收方式:属性传递只能一层层地进行传递,即若想实现父传孙,则必须先父传子,再进行子传孙才可实现,而上下文传递时后代组件可以直接使用父组件设置好的上下文信息,不需要一层层进行传递
4.操作难易程度:属性传递操作起来相对方便简单,而上下文传递操作起来相对繁琐一些


平行组件:兄弟组件或者毫无关系的两个组件

方案一:让两个平行组件拥一个共同的父组件

       父组件中有一些信息,父组件把一个方法传递给A,A中把方法执行(方法执行修改父组件信息值),父组件再把最新的信息传递给B即可,等价于A操作,影响了B

方案二:Redux

进行状态统一管理的类库(适用于任何技术体系的项目)

  • 基本流程
    1.createStore(reducer)创建redux公共状态管理器
    import {createStore} from 'redux';
    let store = createStore(reducer);
    
    2.设置管理员函数reducer(state,action)
    let reducer = (state = {n: 0, m: 0}, action) => {
        switch (action.type) {
            case 'VOTE_SUPPORT':
                state = {...state, n: state.n + 1};
                break;
            case 'VOTE_AGAINST':
                state = {...state, m: state.m + 1};
                break;
        }
        return state;// 只有把最新的STATE返回,原有的状态才会被修改
    };
    
    3.子组件由store.getState()获取公共状态信息,父子的通信可以用组件通信的方案实现
    let {store: {getState}} = this.props,
        {n, m} = getState();
    this.state = {n, m};
    
    4.store.dispatch()派发行为通知reducer修改状态
    
    
    
    5.子组件通过store.subscribe()把方法追加到事件池中让其进行组件的重新渲染
    componentDidMount() {
          this.props.store.subscribe(() => {
              this.forceUpdate();
          });
      }
    
  • 工程化管理目录结构
    |-store
      |- index.js 创建redux容器
      |- action-type.js 宏管理行为派发标识
      |- reducers
        |- index.js 各板块合并后的reducer
        |- xxxReducer.js
      |- actions
        |- index.js 各板块合并后的action
        |- xxxAction.js
  • REACT-REDUX(把REDUX进一步封装,适配REACT项目,让REDUX操作更简洁)
    React提供了自己的一套redux管理体系,其基本流程如下:
    1.工程化管理目录与redux一致
    2.利用Provider把创建的store挂载到祖先元素的上下文中,供内部任何后代组件使用
    render(
        
    , root);
    3.在子组件中通过connect高阶组件实现获取公共状态、重新渲染、行为派发等一系列流程
    import {connect} from 'react-redux';
    // 把REDUX容器中的状态信息遍历,赋值给当前组件的属性(state)
    let mapStateToProps = state => {
        // state:就是REDUX容器中的状态信息
        // return的是啥,就把它挂载到当前组件的属性上(REDUX存储很多信息,想用啥就返回啥即可)
        return {
            ...state.vote
        };
    };
    
    // 把REDUX中的DISPATCH派发行为遍历,也赋值给组件的属性(ActionCreator)
    let mapDispatchToProps = dispatch => {
        // dispatch:STORE中存储的DISPATCH方法
        // 返回的是啥,就相当于把啥挂载到组件的属性上(一般会挂载一些方法,这些方法中完成了DISPATCH派发任务操作)
        return {
            init(initData) {
                dispatch(action.vote.init(initData));
            }
        };
    };
    export default connect(mapStateToProps, mapDispatchToProps)(VoteBase);
    
    // 简化写法
    export default connect(state => ({...state.vote}), action.vote)(VoteBase);     // REACT-REDUX帮我们做了一件事情,把ACTION-CREATOR中编写的方法(返回ACTION对象的方法),自动构建成DISPATCH派发任务的方法,也就是mapDispatchToProps这种格式
    

你可能感兴趣的:(React入门(四))