React 组件间的通信

来源:互联网 发布:宝宝生长曲线软件 编辑:程序博客网 时间:2024/06/05 16:51

    前言:相信很多用过React或者刚刚开始接触的人,对组件间的通信都深有感触,那么下面就我自己的工作经验给大家说一下,因为父子通信大家都比较熟悉,下面介绍的会着重对没有嵌套关系的组件通信。

  一:父传子主要应用props

  二:子传父用回调或者自定义事件

  三:没有嵌套关系组件通信

   我们在处理事件的过程中需要注意,在componentDidMount事件中,如果组件挂载完成,再订阅事件;当组件卸载的时候,在componentEillUnmount事件中取消事件的订阅。

  我们常用的发布/订阅模式来举例,这里借用Node.js Events模块的浏览器版实现。

  对于React使用场景来说,EventEmitter只需要单例就可以,因此我们需要单独初始化EventEmitter实例(以前在应用兄弟间组件通信都是通过父组件实现的,但是如果这样层级较深,做起来简直是噩梦,所以在这里应用一个方法EventEmitter,相信很多人对此都了解)这里附上自己测试页面:


父页面Test

import React, { Component } from 'react';
import List from './List';
import emitter from './events';


class Test extends Component{
  constructor(props){
    super(props);
    this.state = {
      value:[{text:1},{text:2}]
    }
  }
  componentDidMount(){
    this.itemChange = emitter.addListener('ItemChange',(msg,data) => {
      console.log(data,'dddddddd',msg)
    })
  }


  componentWillUnmount(){
    emitter.removeListener(this.itemChange);
  }


  valueChange = value => {
    this.setState({
      value,
    })
  }
  render(){
    return(
      <List list={this.state.value}></List>
    )
  }
}


export default Test
子页面:List

import React, { Component } from 'react';
import ListItem from './ListItem';
import emitter from './events';


class List extends Component{
  constructor(props){
    super(props);
    this.state = {
      list:this.props.list.map(entry => ({
        text:entry.text,
        checked:entry.checked || false,
      }))
    }
  }


  onItemChange(entry){
    const {list} = this.state;
    this.setState({
      list:list.map(preEntry => ({
        text:preEntry.text,
        checked:preEntry.text === entry.text ? !preEntry.checked : preEntry.checked,
      }))
    });
    emitter.emit('ItemChange',entry);
  }


  render(){
    return (
      <div>
        <ul>
          {this.state.list.map((entry,index) => {
            return (
               <ListItem
            key={`list-${index}`}
            value={entry.text}
            checked={entry.checked}
            onChange={this.onItemChange.bind(this,entry)}/>
            )
          })}
        </ul>
      </div>
    )
  }
}




export default List
孙子页面ListItem:

import React, { Component } from 'react';


class ListItem extends Component {
  static defaultProps = {
    checked:false
  }


  constructor(props){
    super(props);
  }
  
  render() {
    return(
      <li>
        <input type='checkbox' checked={this.props.checked} onChange={this.props.onChange}/>
        <span>{this.props.value}</span>
      </li>
    );
  }
}




export default ListItem
触发事件:这里强调一下,要事先安装npm install events

import { EventEmitter } from 'events';
export default new EventEmitter();




现在项目中应用的是antd初始化的项目,所以里面把这些都封装的很好,平常我们应用兄弟通信都是通过dispatch,去改变model中state,比如说,A是父组件有两个子组件B和C,在B中某个事件调用中应用dispatch去改变model中state,C中获取model中改变了的state,就可以达到通信的目的,附带吗;

B中代码:


<TabPane key={item.key} onClick={(key) => {
              this.props.dispatch({
                type:'acceptLetterInfoList/loadMyMailTableList',
                payload:{
                  props:{
                    messageFirst:-1,
                    pageIndex: 1,
                    pageSize: 20
                  }
                }
              });
              this.setState({
                messageFirst:-1,
              });
            }} tab={item.tab}>{item.content}</TabPane>

C中从props中获取:


const { messageFirst } =this.props;

有什么说的不对或者哪里有问题,希望大家贴帖,我们共同讨论