专栏首页OECOMreact组件间的通信

react组件间的通信

在使用react过程中,不可避免的需要组件间的数据通信,数据通信一般情况有一下几种情况:

  1. 父组件向子组件通信
  2. 子组件向父组件通信
  3. 跨级组件之间通信
  4. 非嵌套组件间通信

下面将依次来说一下这几种组件间通信的解决办法。

父组件向子组件通信

这种通信方式是最常见的一种,解决方法就是通过props来进行通信,子组件接收到props后再进行相应的处理。

import React,{Component} from 'react';
import Header from './header'
import './father.less';

class Father extends Component{
  constructor(){
    super();
    this.state={
      myName:"张三"
    }
  }
  render(){
    return (
      <div className="container">
        <Header title={this.state.myName}/>
      </div>
    )
  }
}
export default Father

上面代码为father组件,在其内部引入了header子组件,并将自己的state中的myName传递给header组件,定义名称为title,在子组件中可以通过this.props.title来获取到值。

import React,{Component} from 'react';
import './header.less';

class Header extends Component{
  render(){
    return (
      <div className="components-header row">
        {this.props.myName}
      </div>
    )
  }
}
export default Header

上述代码就是一个简单的父组件向子组件来传递数据。当然,为了保证程序的严谨性,在子组件中我们可以对传递过来的props进行类型校验,如果类型校验没有通过,则会抛出一个错误,已提醒调用组件者。

import React,{Component} from 'react';
import './header.less';

class Header extends Component{
  propsType:{
    title:React.propsTypes.String
  }
  render(){
    return (
      <div className="components-header row">
        {this.props.myName}
      </div>
    )
  }
}
export default Header

如此即完成了对于传递过来的参数校验。

子组件向父组件通信

子组件向父组件通信可以通过回调函数的方式来进行,我们还是将上面的代码来修改一下。

先看father组件

import React,{Component} from 'react';
import Header from './header'

class Father extends Component{
  constructor(){
    super();
    this.state={
      myName:"张三"
    }
  }
  showChildName(name){
    console.log(name);
  }
  render(){
    return (
      <div className="container">
        <Header showName={this.showChildName.bind(this)}/>
      </div>
    )
  }
}
export default Father

其次是子组件

import React,{Component} from 'react';
import './header.less';

class Header extends Component{
  propsType:{
    showName:React.propsTypes.Func
  }
  constructor(){
    super();
    this.state={
      myName:"header"
    }
  }
  showName(){
    let myName = this.state.myName;
    this.props.showName(myName)
  }
  render(){
    return (
      <div className="components-header row">
        <button onClick={this.showName.bind(this)}>按钮</button>
      </div>
    )
  }
}
export default Header

跨组件通信

所谓跨级组件通信,就是父组件向子组件的子组件通信,向更深层的子组件通信。跨级组件通信可以采用下面两种方式:中间组件层层传递props;使用context对象

对于第一种方式,如果父组件结构较深,那么中间的每一层组件都要去传递 props,增加了复杂度,并且这些 props 并不是这些中间组件自己所需要的。不过这种方式也是可行的,当组件层次在三层以内可以采用这种方式,当组件嵌套过深时,采用这种方式就需要斟酌了。 使用 context 是另一种可行的方式,context 相当于一个全局变量,是一个大容器,我们可以把要通信的内容放在这个容器中,这样一来,不管嵌套有多深,都可以随意取用。 使用 context 也很简单,需要满足两个条件:

  1. 上级组件要声明自己支持 context,并提供一个函数来返回相应的 context 对象
  2. 子组件要声明自己需要使用 context

下面请看一个例子

import React, { Component } from 'react';
import Sub from "./Sub";
import "./App.css";

export default class App extends Component{
    // 父组件声明自己支持 context
    static childContextTypes = {
        color:React.propTypes.string,
        callback:React.propTypes.func,
    }
    // 父组件提供一个函数,用来返回相应的 context 对象
    getChildContext(){
        return{
            color:"red",
            callback:this.callback.bind(this)
        }
    }
    callback(msg){
        console.log(msg)
    }
    render(){
        return(
            <div>
                <Sub></Sub>
            </div>
        );
    }
}

sub组件

import React from "react";
import SubSub from "./SubSub";

const Sub = (props) =>{
    return(
        <div>
            <SubSub />
        </div>
    );
}

export default Sub;

subsub组件(孙子组件)

import React,{ Component } from "react";
import PropTypes from "prop-types";

export default class SubSub extends Component{
    // 子组件声明自己需要使用 context
    static contextTypes = {
        color:PropTypes.string,
        callback:PropTypes.func,
    }
    render(){
        const style = { color:this.context.color }
        const cb = (msg) => {
            return () => {
                this.context.callback(msg);
            }
        }
        return(
            <div style = { style }>
                SUBSUB
                <button onClick = { cb("孙子组件信息") }>按钮</button>
            </div>
        );
    }
}

跨组件通信

跨组件通信的方式适用于以上所有的通信方式,这种方式是通过发布/订阅者模式来实现,需要安装PubSub

首先是通过npm来安装pubsub

npm install pubsub-js --save

页面中引入

import PubSub from 'pubsub-js'

pubsub有三中操作,分别是发布消息,订阅消息,取消订阅

发送消息:PubSub.publish(名称,参数)
订阅消息:PubSub.subscrib(名称,函数)
取消订阅:PubSub.unsubscrib(名称)

首先发送消息需要顶一个名称,以供给订阅消息的名称来确定订阅哪个消息,基本上是一个键值对的形式,参数是该键的值,当在组件中注册了订阅消息以后,相当与注册了一个监听事件,当有发布消息发出,订阅消息就会接收到,并在订阅消息的函数中进行自定义处理。取消订阅相当于是取消该监听事件。

home组件

import React, { Component } from 'react';  
import PubSub from 'pubsub-js';  
class Home extends Component {  
  constructor(props){  
    super(props);  
    this.state={  
      increase:'increase',  
      decrease:'decrease'  
    }  
  }  
  buttonIncrease(){  
    PubSub.publish('PubSubmessag',this.state.increase);  
  }  
  buttonDecrease(){  
     PubSub.publish('PubSubmessage', this.state.decrease);  
  }  
  render() {  
    return (  
      <div>  
        Some state changes:  
        <button onClick={this.buttonIncrease.bind(this)}>Increase</button>  
        <button onClick={this.buttonDecrease.bind(this)}>Decrease</button>  
      </div>  
    )  
  }  
}  
export default Home;

子组件

import React, { Component } from 'react';  
import { Link} from 'react-router-dom';  
import PubSub from 'pubsub-js';  
  
export default class App extends Component{  
constructor(props){  
  super(props);  
  this.state={  
    increase:'none',  
  }  
}  
componentDidMount(){  
  this.pubsub_token = PubSub.subscribe('PubSubmessage', function (topic,message) {  
    this.setState({  
      increase: message  
    });  
  }.bind(this));  
}  
componentWillUnmount(){  
  PubSub.unsubscribe(this.pubsub_token);  
}  
  render() {  
  return (  
    <div>  
      <header>  
        Links:       
        <Link to="/App/home">Home</Link>     
      </header>   
      <div style={{ marginTop: '1.5em' }}>{ this.props.children}</div>  
      <div style={{ marginTop: '1.5em' }}>{ this.state.increase}</div>  
    </div>  
  )  
}  
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • React-router 4.0之路由配置

    react-router 4.0已经发布了很长一段时间了,和3.x的API相比改动了很多地方。它遵循React的设计理念,即万物皆组件。所以 RR4 只是一堆提...

    无邪Z
  • js实现拖动组件移动效果

    今天我来给大家介绍一种js特效,这种特效是当你用鼠标点击组件移动到其他地方后,这个组件就定在了那个地方,这种效果通常用来做视图化排版的。下面我来把代码贴出来给大...

    无邪Z
  • React router 4.0之参数传递

    在前一篇文章中说到了react router 4的路由如何配置,这篇文章说一下路由跳转的参数问题。路由跳转传参一种方式是在link标签上写参数,另一种方式是通过...

    无邪Z
  • 你要的 React 面试知识点,都在这了

    React是流行的javascript框架之一,在2019年及以后将会更加流行。React于2013年首次发布,多年来广受欢迎。它是一个声明性的、基于组件的、用...

    Fundebug
  • 你要的 React 面试知识点,都在这了

    React是流行的javascript框架之一,在2019年及以后将会更加流行。React于2013年首次发布,多年来广受欢迎。它是一个声明性的、基于组件的、用...

    前端小智@大迁世界
  • 前端路由0.前言1.哈希路由2.history路由

    后端有后端路由,根据路由返回特定的网页,代表者是传统的mvc模式,模板引擎+node。前端也有前端的路由,我们用三大框架做spa的时候,总是和路由离不开关系。主...

    lhyt
  • 使用react render props实现倒计时

    react的组件模式可以观看Michael Chan的演讲视频,平时大家常听到的react模式也是HOC, HOC的使用场景很多,譬如react-redu...

    IMWeb前端团队
  • 评论列表实例

    DataScience

扫码关注云+社区

领取腾讯云代金券