React教程(三):React组件通信

传送门:
React教程(一):React基础
React教程(二):React组件基础

一.组件通信的意义

组件是独立且封闭的单元,默认情况下组件只能使用自己的数据。(state)
组件化开发的过程中,完整的功能会拆分对个组件,在这个过程中不可避免的需要互相传递一些数据。
为了让各组件之间可以进行互相沟通,数据传递,这个过程就是组件通信。

二.组件通信方式

组件通信方式可以归纳为以下几种情况:

  1. 父子关系(比较常用)
  2. 兄弟关系- 自定义时间模式产生技术方法 eventBus / 通过共同的父组件通信
  3. 其他关系 - mbox / redux / 基于hook的方案### 1.父传子

1.父传子实现

  1. 父组件提供要传递的数据 - state
  2. 给子组件标签添加属性值为state中的数据。
  3. 子组件中通过props接收父组件中传递过来的数据
    1) 类组件中通过this.props
    2) 函数组件直接通过参数获取props对象
    图示:
    在这里插入图片描述

代码演示:

  1. 类组件父传子

// 类组件
class HelloWorld extends React.Component {
    
    
  render() {
    
    
    console.log("传递过来的值:", this.props);
    return <div>{
    
    this.props.message}</div>;
  }
}
class App extends React.Component {
    
    
  // 1.父组件准备好需要传递的信息
  state = {
    
    
    msg: "父组件需要传递的信息",
  };
  render() {
    
    
    return (
      <div>
        {
    
    /* 2.使用子组件时候,将父组件state中的信息添加到子组件标签的属性上,属性名可自定义 */}
        <HelloWorld message={
    
    this.state.msg} />
      </div>
    );
  }
}

效果展示:
在这里插入图片描述
2. 函数组件父传子

// 函数组件
// 3.子组件通过props接收并
// 当然也可以在函数的形参中直接解构 const HelloWorld = ({message}) =>{}
const HelloWorld = (props) => {
    
    
  //解构出父组件传递过来的信息
  const {
    
     message } = props;
  // 使用message
  return <div>{
    
    message}</div>;
};
function App() {
    
    
  // 1.准备好需要传递的信息
  const msg = "父组件需要传递的信息";
  return (
    <div>
      {
    
    /* 2.挂载到子组件的标签属性上 */}
      <HelloWorld message={
    
    msg} />
    </div>
  );
}

2.props说明

  1. props是只读对象(readonly)
    根据单向数据流的特性,子组件只能读取props中的数据,不能进行修改。
    this.props = xxxx // 这种写法达咩
  2. props可以传递任意数据
    数字、字符串、布尔值、数组、对象、函数JSX
// 类组件
class HelloWorld extends React.Component {
    
    
  render() {
    
    
    console.log("props===", this.props);
    return <div>{
    
    this.props.message}</div>;
  }
}

function App() {
    
    
  const msg = "父组件需要传递的信息";
  return (
    <div>
      <HelloWorld
        message={
    
    msg}
        flag={
    
    true}
        ui={
    
    <div>我是jsx元素</div>}
        person={
    
    {
    
    
          name: "icy",
          age: 23,
        }}
        list={
    
    [1, 23, 4, 5, 5]}
        handle={
    
    () => {
    
    
          console.log("我是函数");
        }}
      />
    </div>
  );
}

我们到控制台查看一下打印结果:
在这里插入图片描述
可见信息都被传递过来了。

关于props.children,可以获取子组件标签包裹着的内容。
示例:

// 类组件
class HelloWorld extends React.Component {
    
    
  render() {
    
    
    console.log("props===", this.props);
    return <div>{
    
    this.props.children}</div>;
  }
}

// // 3.子组件通过props接收并
// // 当然也可以在函数的形参中直接解构 const HelloWorld = ({message}) =>{}
// const HelloWorld = (props) => {
    
    
//   //解构出父组件传递过来的信息
//   const { message } = props;
//   // 使用message
//   return <div>{message}</div>;
// };
function App() {
    
    
  const msg = "父组件需要传递的信息";
  return (
    <div>
      <HelloWorld>
        <span>我是被子组件包裹的内容</span>
      </HelloWorld>
    </div>
  );
}

在这里插入图片描述
如果想使用子组件包裹着的内容,只能这样使用,否则包裹的内容会被忽略,不会渲染到页面中。

3. 子传父实现

原理:子组件调用父组件传递过来的函数,将想要传递的数据当成函数的实参传入即可

代码说明:

const Son = (props) => {
    
    
  // 3.子组件接收该回调函数
  const {
    
     getDataFun } = props;
  // 4. 子组件准备好需要传递给父组件的数据
  const msg = "我是来自子组件的数据";
  // 5.调用回调函数,将数据作为实参传入
  getDataFun(msg);
  return <div>我是子组件</div>;
};

function App() {
    
    
  // 1.父组件准备一个回调函数
  const getDataFromSon = (data) => {
    
    
  // 6.获得子组件传递过来的数据并使用
    console.log("data===", data);
  };
  return (
    <div>
      {
    
    /* 2.将函数传递给子组件 */}
      <Son getDataFun={
    
    getDataFromSon} />
    </div>
  );
}

我们可以看到打印出来的结果,来验证传递有无成功。
在这里插入图片描述
此外,该函数调用了即可传递无论它是在哪里被调用的。
举个例子:

const Son = (props) => {
    
    
  // 3.子组件接收该回调函数
  const {
    
     getDataFun } = props;
  // 4. 子组件准备好需要传递给父组件的数据
  const dealFunc = () => {
    
    
    const msg = "我是来自子组件的数据";
    // 5.调用回调函数,将数据作为实参传入
    getDataFun(msg);
  };
  return <div onClick={
    
    dealFunc}>我是子组件</div>;
};

即使它放在div的电机事件dealFunc中执行,那么点击div时那他还是算执行了getDataFun,数据一样会被传递到父组件中。

4.兄弟组件传递

原理:通过状态提升机制,利用共同的父组件实现兄弟通信
1.先把子组件2中的数据传递给父组件
2.再把父组件中收到的数据保存下来,传给子组件1
从而实现了组件2 - > 组件1
在这里插入图片描述
代码基本实现:


// 子组件1
const Son1 = (props) => {
    
    
  // 4.准备一个需要传递给son2的数据
  const son1Data = "我是来自son1的数据";
  // 5.接受父组件传递过来的回调函数
  const {
    
     getDataFromSon1 } = props;

  return (
    <button
      onClick={
    
    () => {
    
    
        // 6.将数据传递给父组件app
        getDataFromSon1(son1Data);
      }}
    >
      我是son1,点我数据会传给son2
    </button>
  );
};
// 子组件2
const Son2 = (props) => {
    
    
  // 8.接受从父组件传递过来的son1数据
  const {
    
     son1Data } = props;

  return <div>这里son2组件,son1传递过来的数据是:{
    
    son1Data}</div>;
};

// 父组件
class App extends React.Component {
    
    
  // 1.准备一个状态存储来自son1的数据
  state = {
    
    
    son1Data: "", // 初始值为空字符
  };
  // 2.准备一个回调函数,接收来自son1的数据
  getDataFromSon1 = (data) => {
    
    
    this.setState({
    
    
      ...this.state,
      son1Data: data,
    });
  };
  render() {
    
    
    return (
      <div>
        {
    
    /* 3.传递回调函数 */}
        <Son1 getDataFromSon1={
    
    this.getDataFromSon1} />
        {
    
    /* 7.将从son1组件接收到的数据传给son2组件 */}
        <Son2 son1Data={
    
    this.state.son1Data} />
      </div>
    );
  }
}

效果如下,点击后son1的数据传到了son2:
在这里插入图片描述

5.跨组件通信Context

场景:
实现根据组件直接跨越组件A,传递数据给组件C
在这里插入图片描述

 上面是一个react形成的嵌套树,如果我们想从APP组件向一个下层任意组件传递数据,目前我们能采取的方式是一层一层的props往下传,显然这很繁琐。
 所以,Context提供了一个无需为每层组件手动添加props,就能在组件树之间进行数据传递的方法。

实现步骤:
1.创建Context对象,导出Provider和Consumer对象

const {
    
     Provider, Consumer } = createContext;
  1. 使用Provider包裹提供数据的组件并且提供数据
 <Provider value={
    
    this.state.msg}>
        <SonA />
 </Provider>
  1. 需要用到数据的组件用Consumer包裹获取数据
   <Consumer>{
    
    (value) => <span>拿到的数据是:{
    
    value}</span>}

完整代码如下:

// 引入react核心包
import React, {
    
     createContext } from "react";

const {
    
     Provider, Consumer } = createContext();
// 子组件1
const SonA = () => {
    
    
  return (
    <div>
      这里是组件A
      <SonB />
    </div>
  );
};
// 子组件B
const SonB = () => {
    
    
  return (
    <div>
      这里是组件B
      <SonC />
    </div>
  );
};

// 子组件C
const SonC = (props) => {
    
    
  return (
    <div>
      这里是组件C
      {
    
    /* 使用Consumer包裹需要使用数据的组件,并且使用回调函数的方式使用数据 */}
      <Consumer>{
    
    (value) => <span>拿到的数据是:{
    
    value}</span>}</Consumer>
    </div>
  );
};
// 根组件
class App extends React.Component {
    
    
  state = {
    
    
    msg: "11111好耶111",
  };

  render() {
    
    
    return (
      // 使用provider包裹根组件并提供数据
      <Provider value={
    
    this.state.msg}>
        <div>
          <SonA />
        </div>
      </Provider>
    );
  }
}

export default App;

组件关系如图:
app->组件A->组件B->组件C
在这里插入图片描述

6.额外(React Developer Tools 谷歌浏览器插件)

谷歌商店下载链接:https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi
(访问不了的可以挂梯子,懂的都懂。)

如果实在没有的话,可以去极简插件下载:
下载地址:https://chrome.zzzmh.cn/info/fmkadmapgofadopljbjfkapdkoienihi

这个插件的好处是可以监听你的react构建的页面,用过dev-tools的应该都知道怎么用。
然后就可以看到react组件的层级结构了,非常的nice:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43682422/article/details/129818652