主要有以下几种情况需要考虑:

  • 父子
  • 子父
  • 兄弟
  • 爷孙

1. 父子通信

  • 传参:props
//父组件
import React from 'react';
import { withRouter } from 'react-router-dom';
import Child from './Child';
class Parent extends React.Component{
    constructor(props){
        super(props);
        this.state={
            name: '父组件'
        }
    }

    render() {
        return <div className=''>
            <Child name={this.state.name}></Child>
        </div>
    }
}

export default withRouter(Parent);

----------------------------------------------------

//子组件
import React from 'react';
export default class Child extends React.Component{
    constructor(props){
        super(props);
        this.state={

        }
    }

    componentDidMount() {
        console.log('父组件传递的值是:', this.props.name)
    }

    render() {
        return <div className=''>
            <div>子组件content</div>
        </div>
    }
}
  • 调用方法:refs
// 父组件
import React from 'react';
import { withRouter } from 'react-router-dom';
import Child from './Child';
class Parent extends React.Component{
    constructor(props){
        super(props);
        this.state={
            name: '父组件'
        }
        // 1. 创建Refs
        this.myRef = React.createRef();
    }

    componentDidMount() {
        // 2. 访问 Refs
        this.myRef.current.childMethod();
    }

    render() {
        return <div className=''>
            {/*1. 创建Refs*/}
            <Child name={this.state.name} ref={this.myRef}></Child>
        </div>
    }
}

export default withRouter(Parent);

分为两个步骤:

  1. 创建Refs: 通过React.createRef()创建refs,并通过 ref 属性附加到 React 元素。
this.myRef = React.createRef();
<Child name={this.state.name} ref={this.myRef}></Child>
  1. 访问 Refs:当 ref 被传递给 render 中的元素时,对该节点的引用可以在 ref 的 current 属性中被访问。
this.myRef.current.childMethod();

其中,ref 的值根据节点的类型而有所不同:(来自官网)

  • 当 ref 属性用于 HTML 元素时,构造函数中使用 React.createRef() 创建的 ref 接收底层 DOM 元素作为其 current 属性。
  • 当 ref 属性用于自定义 class 组件时,ref 对象接收组件的挂载实例作为其 current 属性。
  • 不能在函数组件上使用 ref 属性,因为他们没有实例。

2. 子父通信

  • 传参&&调用方法:props的回调
//父组件
import React from 'react';
import { withRouter } from 'react-router-dom';
import Child from './Child';
class Parent extends React.Component{
    constructor(props){
        super(props);
        this.state={
            
        }
    }

    parentMethod = (child_name) => {
        //接收子组件传递的参数
        console.log('子组件传递的值是:', child_name)
    }

    render() {
        return <div className=''>
            <Child name={this.state.name} ref={this.myRef} parentMethod={this.parentMethod}></Child>
        </div>
    }
}

export default withRouter(Parent);

---------------------------------------------------

// 子组件
import React from 'react';
export default class Child extends React.Component{
    constructor(props){
        super(props);
        this.state={

        }
    }

    componentDidMount() {
       //调用父组件的方法并传递参数
        this.props.parentMethod('child_name')
    }
    
    render() {
        return <div className=''>
            <div>子组件content</div>
        </div>
    }
}

3. 兄弟组件

  • 传参
  1. 通过共同的父节点来充当参数传递的中介
  2. 基于发布订阅模式:eventEmitter
//事件总线
import { EventEmitter } from 'events';
export default new EventEmitter();

---------------------------------------------------

// 子组件1
import React from 'react';
import event from './events';//引入创建的EventEmitter实例
export default class Child1 extends React.Component{
    constructor(props){
        super(props);
        this.state={
            name: 'child1'
        }
    }

    componentDidMount() {
        //发送事件
        event.emit('my_event', this.state.name)//child2接收不到
    }

    handleClick = () => {
        //发送事件
        event.emit('my_event', this.state.name)//child2可以接收到

    }

    render() {
        return <div className=''>
            <div onClick={this.handleClick}>子组件1的content</div>
        </div>
    }
}

---------------------------------------------------

// 子组件2
import React from 'react';
import event from './events';
export default class Child2 extends React.Component{
    constructor(props){
        super(props);
        this.state={

        }
    }

    componentDidMount() {
        event.addListener('my_event', msg => {
            console.log('接收到的来自child1的参数是:', msg)
        })  
    }

    render() {
        return <div className=''>
            <div>子组件2的content</div>
        </div>
    }
}
  1. 状态管理库(这里使用mobx)
//store
import { observable, action, decorate } from 'mobx';

export default class GlobalStore {
    constructor(rootStore) {
        this.rootStore = rootStore;
        this.state = observable({
            info: ''
        });
    }

    // update actions
    updateStore(key, data) {
        this.state[key] = data;
    }
}

decorate(GlobalStore, {
    updateStore: action,
})

---------------------------------------------------


// 子组件1
import React from 'react';
import { observer, inject } from 'mobx-react';
class Child1 extends React.Component{
    constructor(props){
        super(props);
        this.state={
        }
    }

    componentDidMount() {
        //改变store中的state
        this.props.globalStore.updateStore('info', 'change from child1');
    }


    render() {
        return <div className=''>
            <div>子组件1的content</div>
        </div>
    }
}

export default inject('globalStore')(
    observer(Child1)
)

---------------------------------------------------

// 子组件2
import React from 'react';
import { observer, inject } from 'mobx-react';
class Child2 extends React.Component{
    constructor(props){
        super(props);
        this.state={

        }
    }

    componentDidMount() {
        //访问的store中的参数
        console.log('this.props.store:', this.props.globalStore.state.info)
    }

    render() {
        return <div className=''>
            <div>子组件2的content</div>
        </div>
    }
}

export default inject('globalStore')(
    observer(Child2)
)

4. 爷孙组件

  • 传参:context(以下为demo,官网也有具体用法)、eventEmitter(参考3)
//公共context
import React from 'react';
const ThemeContext = React.createContext('default_value');
export default ThemeContext;

---------------------------------------------------

// 父组件
import React from 'react';
import { withRouter } from 'react-router-dom';
import Child from './child';
import ThemeContext from './themeContext';

class Parent4 extends React.Component{
    constructor(props){
        super(props);
        this.state={
        }
    }

    componentDidMount() {

    }

    render() {
        return <div className=''>
            <ThemeContext.Provider value='sklnfdnsjfnkdnfkndf'>
                <Child></Child>
            </ThemeContext.Provider>
        </div>
    }
}

export default withRouter(Parent4);

---------------------------------------------------

// 孙组件
import React from 'react';
import ThemeContext from './themeContext';


export default class GrandSon extends React.Component{
    constructor(props){
        super(props);
        this.state={
        }
    }

    componentDidMount() {
        //访问到爷爷组件中传递的参数
        console.log('this.context...', this.context)
    }

    render() {
        return <div className=''>
            
        </div>
    }
}
GrandSon.contextType=ThemeContext;//将contextType挂在class上,有助于在class的任何地方都能访问到this.context

步骤:

  1. 创建一个 Context 对象。当 React 渲染一个订阅了这个 Context 对象的组件,这个组件会从组件树中离自身最近的那个匹配的 Provider 中读取到当前的 context 值。
const ThemeContext = React.createContext('default_value');
  1. 每个 Context 对象都会返回一个 Provider React 组件,它允许消费组件订阅 context 的变化。
<ThemeContext.Provider value='sklnfdnsjfnkdnfkndf'>
    <Child></Child>
</ThemeContext.Provider>
  1. 利用this.context访问到根组件传递的参数

希望大家能持续关注哦,留一些个人信息方便大家找到我哦。github


前端子金
9 声望0 粉丝