写点什么

React 组件通信

作者:xiaofeng
  • 2022-11-09
    浙江
  • 本文字数:2612 字

    阅读完需:约 9 分钟

react 因为组件化,使得组件间通信十分的重要。本文就来简单介绍一些常见的 react 组件间传递的内容。我将归纳为以下几种关系来详述:父组件与子组件之间子组件与父组件之间发布者与订阅者模式(context)兄弟组件间,redux 也是一种组件管理的方法,但是 redux 状态管理的内容比较多,这里只做简单介绍,之后再另开一篇详述。

父组件向子组件通信

react 的数据流是单向的,最常见的就是通过 props 由父组件向子组件传值。

示例(关键部分有注释):

我们做一个简单的选择商品,然后改变价格的事例。



父组件:父组件就是两个按钮,用来切换商品的价格,其中引用了子组件。


class Parents extends Component {   //构造函数  constructor() {    super();    // 设置state    this.state = {      price: 0    };  }
clickGoods(e) { //更新state this.setState({ price: e });}

// 渲染 render() { let { price } = this.state; return ( <div> <button onClick={this.clickGoods1.bind(this)}>goods1</button> <button onClick={this.clickGoods2.bind(this)}>goods2</button> // 父组件中 <Child price={price} /> </div> ); }}
复制代码


子组件:子组件中使用 props 属性接收传递来的数据。


class Child extends Component {  render() {  {/*这里从props中拿到*/}    return <div> price: {this.props.price} </div>;  }}
复制代码

子组件向父组件通信

接下来我们反过来,让子组件向父组件通信。 子组件向父组件通信的基本思路是,父组件向子组件传一个函数,然后通过这个函数的回调,拿到子组件传过来的值。下面是例子,正好和上面是反的,父组件用来显示价格,子组件显示两个按钮,子组件把价格传递给父组件。

示例(关键部分有注释):


父组件


class Parents extends Component {  constructor() {    super();    this.state = {      price: 0    };  }
getItemPrice(e) { this.setState({ price: e }); }
render() { return ( <div> <div>price: {this.state.price}</div> {/* 向子组件中传入一个函数 */} <Child getPrice={this.getItemPrice.bind(this)} /> </div> ); }}
复制代码


子组件


class Child extends Component {  clickGoods(e) {    // 在此函数中传入值    this.props.getPrice(e);  }
render() { return ( <div> <button onClick={this.clickGoods.bind(this, 100)}>goods1</button> <button onClick={this.clickGoods.bind(this, 1000)}>goods2</button> </div> ); }}
复制代码

发布者与订阅者模式(context)

React 的 props 都是由父组件传递给子组件的,一旦遇到孙组件,就需要一层层的传递下去。而 context 提供了一种组件之间通讯的新的方式(16.3 版本之后),可以共享一些数据,其它的组件都能从 context 中读取数据(类似于有个数据源,组件可以订阅这个数据源)。


参考 React 实战视频讲解:进入学习

使用方法

React.createContext()方法

我们可以使用 createContext 来创建一个 context,它可以接收一个变量或者对象做为参数(当对象为参数的时候,react 使用 object.is()去比较,有些影响性能)。这个传入的值做为 context 的默认值


 const PriceContext = React.createContext('price')
复制代码


这样就创建了一个 Context

Provider 组件

Provider 就是用来创建数据源的。它是给所有的子组件提供数据源的跟组件。它接受一个 value 作为 props,用来传递值,它会改变 context 的默认值。一个 provider 可以包含多个 Consumer 组件。如果 Provider 组件嵌套的话,


<PriceContext.Provider value={100}></PriceContext.Provider>
复制代码

Consumer 组件

Consumer 表示接受数据的组件,它接受一个函数做为子元素。这个函数会接收 context 传递的值,返回一个 react 的组件。Consumer 组件必须包含在 Provider 里面。


<PriceContext.Consumer>    { /*这里是一个函数*/ }    {        price => <div>price:{price}</div>    }</PriceContext.Consumer>
复制代码

示例

在这部分我们尝试一下从父组件直接传递到孙组件,不通过子组件(直接从 A 组件传值到 C 组件,不经过 B 组件)。



// 创建Contextconst PriceContext = React.createContext('price')// A组件中class ClassA extends Component {  constructor(){    super()    this.state={      price:0    }  }  // 点击按钮事件  clickGoods(e) {    this.setState({      price:e    })  }  render(){    const { price } = this.state    return(      // Provider      // 把state里price转到Provider的value中    <PriceContext.Provider value={price}>        <button onClick={this.clickGoods.bind(this, 100)}>goods1</button>        <button onClick={this.clickGoods.bind(this, 1000)}>goods2</button>        <ClassB />    </PriceContext.Provider>      )  }}// 组件Bclass ClassB extends Component {  // 组件B中只是引用了ClassC,没有进行传值的操作  render(){    return(      <div><span>price:</span><span><ClassC /></span></div>    )  }}// 组件Cclass ClassC extends Component {  render(){        return(      // Consumer,注意Consumer的下面要包含一个函数      <PriceContext.Consumer>        {          price=><span>{price}</span>        }      </PriceContext.Consumer>    )  }}
复制代码

context 的总结与理解

一个 react app 是由很多 react 组件组成的,有的组件之间是有嵌套关系的,可以形成一条“组件链”。Context 可以当做组件的“作用域”[3]。一个根组件,它定义了一个 context,它的组件链上的组件都可以访问到 provider 中定义的变量或对象,如下图所示,这就比较像‘作用域’的概念。context 在一些简单的场景下可以替代部分 redux 的功能。


兄弟组件间通信

兄弟间组件通信,一般的思路就是找一个相同的父组件,这时候既可以用 props 传递数据,也可以用 context 的方式来传递数据。当然也可以用一些全局的机制去实现通信,比如 redux 等。

小结

本文主要介绍了 3 种通信的关系父组件与子组件之间子组件与父组件之间发布者与订阅者模式(context),简述了兄弟组件间的通信。主要是介绍两种方式,利用 props 属性和 Context。也介绍了一些 context 的理解。


用户头像

xiaofeng

关注

努力写代码中 2022-08-18 加入

努力写代码中

评论

发布
暂无评论
React组件通信_React_xiaofeng_InfoQ写作社区