美文网首页React
React实现跨组件通讯

React实现跨组件通讯

作者: coderhzc | 来源:发表于2021-12-21 18:15 被阅读0次
以前可以使用一层一层的往下传递,这种可以解决需求,

1.父组件往孙子组件传值:

App.js

import React, { Component } from 'react'
import Profile from './Profile'

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      nikename:"coderhzc",
      level:88
    }
  }
  render() {
    const {nikename,level} = this.state
    return (
      <div>
        <Profile nikename={nikename} level={level}/>
      </div>
    )
  }
}

profile.js文件(注意是函数组件)

import React from 'react';
import ProfileHeader from './ProfileHeader';

export default function Profile(props) {
  // 从父组件传递过来的
  console.log(props,"profile");
  return (
    <div>
      <ProfileHeader nikename={props.nikename} level={props.level}/>
      <ul>
        <li>设置1</li>
        <li>设置2</li>
        <li>设置3</li>
        <li>设置4</li>
      </ul>
    </div>
  )
}

ProfileHeader.js 是profile.js 的子文件 (注意是函数组件)

import React from "react";

export default function ProfileHeader(props) {
  console.log(props,"ProfileHeaderProfileHeaderProfileHeader");
  return (
    <div>
      <h2>用户昵称: {props.nikename}</h2>
      <h2>用户等級: {props.level}</h2>
    </div>
  );
}

实际截图

image.png

** 以上可以实现但是非父子组件就搞不定了 **

补充以上缺陷使用属性展开 {...props},就可以省略Profile.js中的那段多余的传值

image.png

2. 跨组件通讯Context应用场景

Context相关API

(1) React.createContext
 --创建一个需要共享的Context对象:
-- 如果一个组件订阅了Context,那么这个组件会从离自身最近的那个匹配的 Provider 中读取到当前的context值;
 -- defaultValue是组件在顶层查找过程中没有找到对应的Provider,那么就使用默认值
const myContext = React.create


(2) Context.Provider
-- 每个 Context 对象都会返回一个 Provider React 组件,它允许消费组件订阅 context 的变化:
-- Provider 接收一个 value 属性,传递给消费组件;
-- 一个 Provider 可以和多个消费组件有对应关系;
-- 多个 Provider 也可以嵌套使用,里层的会覆盖外层的数据;
-- 当 Provider 的 value 值发生变化时,它内部的所有消费组件都会重新渲染;
<MyContext.Provider value={/*某个值*/}>

(3) Class.contextType
-- 挂载在 class 上的 contextType 属性会被重赋值为一个由 React.createContext() 创建的 Context 对象:
-- 这能让你使用 this.context 来消费最近 Context 上的那个值; p 你可以在任何生命周期中访问到它,包括 render 函数中;
MyClass.contextType = MyContext

(4) Context.Consumer
-- 这里,React 组件也可以订阅到 context 变更。这能让你在 函数式组件 中完成订阅 context。 
-- 这里需要 函数作为子元素(function as child)这种做法; 
-- 这个函数接收当前的 context 值,返回一个 React 节点;
<MyContext.Consumer>
  {value => /*基于context值进行渲染*/}
</MyContext.Consumer>

(4.1) Class 类组件的具体使用代码如下:

import React, { Component } from "react";

// 1.创建Context对象
// defaultValue是组件在顶层查找过程中没有找到对应的Provider,那么就使用默认值
// const UserContext = React.createContext(defaultValue)
export const UserContext = React.createContext({
  nikename: "aaaaa",
  level: -100,
});


// 组件
// 3. 具体的使用方式,记住不能使用函数组件
class ProfileHeader extends Component {
  render() {
    console.log(this.context);
    return (
      <div>
        <h2>用户昵称: {this.context.nikename}</h2>
        <h2>用户等級: {this.context.level}</h2>
      </div>
    );
  }
}
// 4. 把创建的Context对象赋值给ProfileHeader的contextType就可以在孙子组件中拿到从爷爷组件传递的数据了
ProfileHeader.contextType = UserContext;

function Profile(props) {
  return (
    <div>
      <ProfileHeader />
      <ul>
        <li>设置1</li>
        <li>设置2</li>
        <li>设置3</li>
        <li>设置4</li>
      </ul>
    </div>
  )
}


export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      objName: {
        nikename: "coderhzc",
        level: 88,
      },
    };
  }
  render() {
    return (
      <div>
        {/* 2.具体使用 */}
        {/* 
           (1) Provider 接收一个 value 属性,传递给消费组件;
           (2) 当 Provider 的 value 值发生变化时,它内部的所有消费组件都会重新渲染;
         */}
        <UserContext.Provider value={this.state.objName}>
          <Profile />
        </UserContext.Provider>
      </div>
    );
  }
}

实际截图

image.png

### (4.2) 函数组件的具体使用代码如下:

import React, { Component } from "react";

// 1.创建Context对象
// defaultValue是组件在顶层查找过程中没有找到对应的Provider,那么就使用默认值
// const UserContext = React.createContext(defaultValue)
const UserContext = React.createContext({
  nikename: "aaaaa",
  level: -100,
});

// 组件
// 3. 函数组件的具体使用
function ProfileHeader() {
  return (
    <div>
      <UserContext.Consumer>
        {
         value => {
          console.log(value);
          return (
            <div>
              <h2>用户昵称: {value.nikename}</h2>
              <h2>用户等級: {value.level}</h2>
            </div>
          );
        }
        }
      </UserContext.Consumer>
    </div>
  );
}

function Profile(props) {
  return (
    <div>
      <ProfileHeader />
      <ul>
        <li>设置1</li>
        <li>设置2</li>
        <li>设置3</li>
        <li>设置4</li>
      </ul>
    </div>
  );
}

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      objName: {
        nikename: "coderhzc11",
        level: 88,
      },
    };
  }
  render() {
    return (
      <div>
        {/* 2.具体使用 */}
        {/* 
           (1) Provider 接收一个 value 属性,传递给消费组件;
           (2) 当 Provider 的 value 值发生变化时,它内部的所有消费组件都会重新渲染;
         */}
        <UserContext.Provider value={this.state.objName}>
          <Profile />
        </UserContext.Provider>
      </div>
    );
  }
}

实际截图

image.png

5. 多个Context使用代码如下(不推荐做):

import React, { Component } from 'react';

// 创建Context对象
const UserContext = React.createContext({
  nickname: "aaaa",
  level: -1
})

const ThemeContext = React.createContext({
  color: "black"
})

function ProfileHeader() {
  // jsx -> 嵌套的方式
  return (
    <UserContext.Consumer>
      {
        value => {
          return (
            <ThemeContext.Consumer>
              {
                theme => {
                  return (
                    <div>
                      <h2 style={{color: theme.color}}>用户昵称: {value.nickname}</h2>
                      <h2>用户等级: {value.level}</h2>
                      <h2>颜色: {theme.color}</h2>
                    </div>
                  )
                }
              }
            </ThemeContext.Consumer>
          )
        }
      }
    </UserContext.Consumer>
  )
}

function Profile(props) {
  return (
    <div>
      <ProfileHeader />
      <ul>
        <li>设置1</li>
        <li>设置2</li>
        <li>设置3</li>
        <li>设置4</li>
      </ul>
    </div>
  )
}

export default class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      nickname: "kobe",
      level: 99
    }
  }

  render() {
    return (
      <div>
        <UserContext.Provider value={this.state}>
          <ThemeContext.Provider value={{ color: "red" }}>
            <Profile />
          </ThemeContext.Provider>
        </UserContext.Provider>
      </div>
    )
  }
}

实际截图

image.png

终极写法:组件抽离的写法

image.png

相关文章

  • React实现跨组件通讯

    以前可以使用一层一层的往下传递,这种可以解决需求, 1.父组件往孙子组件传值: App.js profile.js...

  • 9天深入react(2-1)-Context

    组件跨层级通讯-Context Context API React.createContext 创建一个Con...

  • 疑问汇总

    1. react context是怎样实现 跨组件通信的? 从Context源码实现谈React性能优化[http...

  • React-redux

    React-redux 底层:通过高阶组件 + context跨组件传值实现,用 包裹根元素, 解决了在组件中频繁...

  • react拖曳组件react-dnd的简单封装使用

    分享原因 由于项目中需要使用拖曳组件(需求:全局,跨组件,跨数据),我选择了react-dnd 概念 React ...

  • react组件通信

    react组件通信是一个常用功能,在做react项目中经常遇到 React组件层级关系 在了解Reat组件通讯之前...

  • react父子通讯

    父子通讯父传数据给子,子传数据给父 react组件class 组件名 extends React.Componen...

  • 事件总线

    在 React 中,我们通常依赖 events 库来实现跨组件之间的事件传递 安装命令: yarn add eve...

  • react-native 初体验

    react-native 常用组件 基础组件: 交互组件(跨平台) TabBarIos 常用属性: TabBarI...

  • React native全局变量的使用(跨组件的通信)

    React native全局变量的使用(跨组件的通信) 标签(空格分隔): React React native全...

网友评论

    本文标题:React实现跨组件通讯

    本文链接:https://www.haomeiwen.com/subject/bibxqrtx.html