react的组件通信

组件间通信的4种情况

  • 父组件向子组件通信
  • 子组件向父组件通信
  • 跨级组件通信
  • 没有嵌套关系组件之间的通信

父组件向子组件通信

父组件向自组件传递信息是最常见的,父组件通过props 向自组件传递需要的信息。

import React, { Component } from 'react';
import Child from './Child';
export default class Parent extends Component {
    render() {
        return (
            <div>
                <Child name="Sara" />
            </div>
        );
    }
}
 
/子组件
import React from 'react';
 
export default function Child({ name }) {  // 解构赋值
    return <h1>Hello, {name}</h1>
}

不常见的方法:ref 利用ref对子组件进行标记。在父组件中直接调用子组件的方法实现通信。不推荐使用。

 
        var Father = React.createClass({
           hitSon(){
            //  this.refs.son.setState({doing : '学习'})
             this.refs.son.goToStudy() //通过refs调用子组件的方法
           },
            render:function () {
                return (
                    <div>
                       父组件:
                       <button onClick={this.hitSon}>go</button>
                       <hr/>
                       <Son ref='son'/>
                    </div>
                )
            }
 
        })
 
        var Son = React.createClass({
            getInitialState(){
                return {
                    doing:'玩游戏'
                }
            },
            goToStudy(){
                this.setState({doing:'学习'})
            },
            render:function () {
                return (
                    <div>
                        子组件:
                        <p>正在{this.state.doing}...</p>
                    </div>
                )
            }
        })
        ReactDOM.render(<Father/>,document.getElementById("app"))

子组件向父组件传递信息

  • 子组件更新组件状态,通过回调函数的方式传递给父组件。
    子组件调用父组件通过props传给它的函数更新父组件state,进而完成子组件向父组件的通讯。
  • 利用自定义事件机制

利用回调函数
简单的说就是把父组件的方法通过props传递给子组件,子组件通过执行父组件方法的形式将信息传递给父组件。

import React, { Component } from 'react';
import Child from './child.js'; 

export default class Parent extends Component {
  state = {
    msg: 'parent'
  }
  callback=(msg)=>{
    this.setState({msg});
  }

  render() {
    return (
      <div>
        <Child callback={this.callback} ></Child>
      </div>
    );
  }
}

import React from "react";

export default class Child extends React.Component{

	state={
	  msg: "Child"
    }
    render(){
        return(
            <div>
                <button onClick={()=>this.props.callback(this.state.msg)}>go</button>
            </div>
        )
    }
}


跨级组件间通信

  • 层层组件传递props
  • 使用context

层层组件传递props {…this.props}

同 props

context

在react没有类似vue中的事件总线来解决这个问题,我们只能借助它们共同的父级组件来实现,将非父子关系装换成多维度的父子关系。react提供了context api来实现跨组件通信, React 16.3之后的contextapi较之前的好用。

  • context是一个全局变量,像是一个大容器,在任何地方都可以访问到,我们可以把要通信的信息放在context上,然后在其他组件中可以随意取到;
  • 但是React官方不建议使用大量context,尽管他可以减少逐层传递,但是当组件结构复杂的时候,我们并不知道context是从哪里传过来的;
  • 实例,使用context 实现购物车中的加减功能
// counterContext.js
import React, { Component, createContext } from 'react'  //第一步导出context

const {
  Provider,
  Consumer: CountConsumer   // 解构起别名
} = createContext()    //解构出Consumer和Provider

class CountProvider extends Component {
  constructor () {
    super()
    this.state = {
      count: 1
    }
  }
  increaseCount = () => {
    this.setState({
      count: this.state.count + 1
    })
  }
  decreaseCount = () => {
    this.setState({
      count: this.state.count - 1
    })
  }
  render() {
    return (
      <Provider value={{			// 第三步 使用Provider包裹
        count: this.state.count,
        increaseCount: this.increaseCount,
        decreaseCount: this.decreaseCount
      }}
      >
        {this.props.children}
      </Provider>
    )
  }
}

export {
  CountProvider,
  CountConsumer
}
// 定义CountButton组件
const CountButton = (props) => {
  return (
    <CountConsumer>
      // consumer的children必须是一个方法
      {
        ({ increaseCount, decreaseCount }) => {
          const { type } = props
          const handleClick = type === 'increase' ? increaseCount : decreaseCount
          const btnText = type === 'increase' ? '+' : '-'
          return <button onClick={handleClick}>{btnText}</button>
        }
      }
    </CountConsumer>
  )
}
// 定义count组件,用于显示数量
const Count = (prop) => {
  return (
    <CountConsumer>
      {
        ({ count }) => {
          return <span>{count}</span>
        }
      }
    </CountConsumer>
  )
}
// 组合
class App extends Component {
  render () {
    return (
  		<CountProvider>
        <CountButton type='decrease' />
        <Count />
        <CountButton type='increase' />
      </CountProvider>
  	)
  }
}

复杂的非父子组件通信在react中很难处理,多组件间的数据共享也不好处理,在实际的工作中我们会使用flux、redux、mobx来实现

没有嵌套关系的组件通信

参考代码来自:gongf

  • 使用自定义事件机制,也就是事件抛发,在List1中侦听changeMessage事件,在List2中抛发事件,完毕后在钩子函数中卸载

yarn add events
在src下新建一个util目录里面建一个events.js

import {EventEmitter} from 'events';
export default new EventEmitter();   
//list.jsx
import React, { Component } from 'react';
import emitter from '../util/events';
 
export default class List extends Component {
    constructor(props) {
        super(props);
        this.state = {
            message: 'List1',
        };
    }
    componentDidMount() {
        // 组件装载完成以后声明一个自定义事件
        this.eventEmitter = emitter.addListener('changeMessage', (message) => {
            this.setState({
                message,
            });
        });
    }
    componentWillUnmount() {
        emitter.removeListener(this.eventEmitter);
    }
    render() {
        return (
            <div>
                {this.state.message}
            </div>
        );
    }
}
 

//list2.jsx
import React, { Component } from 'react';
import emitter from '../util/events';
 
export default class List2 extends Component {
    handleClick = (message) => {
        emitter.emit('changeMessage', message);
    };
    render() {
        return (
            <div>
                <button onClick={this.handleClick.bind(this, 'List2')}>点击我改变List1组件中显示信息</button>
            </div>
        );
    }
}
//APP.jsx
import React, { Component } from 'react';
import List1 from './components/List1';
import List2 from './components/List2';
 
 
export default class App extends Component {
    render() {
        return (
            <div>
                <List1 />
                <List2 />
            </div>
        );
    }
}

redux

redux作为独立于react的数据管理仓库,之后再说。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MaxLoongLvs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值