react中的父子组件通信和跨级组件通信

父子组件通信

顾名思义就是父组件和子组件之间进行通信交流。下面先看样例代码:

// 父子组件通信
import React from "react";

// 下面为父子组件通信实例代码
// 父组件
class ParentSon extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      msg: "father",
      name: "partent",
      age: 60
    };
  }

  callback = (msg, name, age) => {
    this.setState({ msg });
    this.setState({ name });
    this.setState({ age });
  };

  render() {
    return (
      <div style={{padding: 30+'px'}}>
        <h1>{this.state.msg}</h1>
        <Child
          callback={this.callback}
          age={this.state.age}
          name={this.state.name}
        ></Child>
      </div>
    );
  }
}

// 子组件
class Child extends React.Component{
  constructor(props){
    super(props);
    this.state={
      msg: 'I am son',
      name: 'son',
      age: 8
    };
    // 下面一行代码是为了解决非箭头函数使用时this的指向问题不能指向当前子组件自身
    // this.change=this.change.bind(this);
  }
  // change(){
  //   // console.log(this);
  //   this.props.callback(this.state.msg,this.state.name,this.state.age);
  // }
  change=()=>{
    this.props.callback(this.state.msg,this.state.name,this.state.age);
  }

  render(){
    return (
      <div>
        <div>{this.props.name}</div>
        <div>{this.props.age}</div>
        <button onClick={this.change}>点击</button>
      </div>
    )
  }
}

export default ParentSon;

如上面代码所示,分别创建了父组件 ParentSon 和子组件 Child ,父组件里面定义了自己的state内容,并定义了一个 callback 方法,此方法用来改变父组件自身的state内容值的,然后render函数里面除了渲染自身state里的msg值之外,将自身的callback方法以及自身state里的name,age分别作为参数传给了子组件 Child。

下面再继续看子组件内部,除了有自己的state之外,还有一个change方法,然后render函数里渲染了来自props里的值以及一个点击事件按钮,而这个按钮点击事件就会触发调用自身那个change事件,在进入change方法内部会看到,实际上,执行的就是props接收的callback方法,也就是从父组件传过来的那个callback,而这里的参数又是子组件自身state的内容值,到此,我们可以顺一下整个思路了。

思路: 一开始渲染出的全是父组件的值(因为子组件显示的就是来自父组件的值)-----> 点击按钮 -----> 触发子组件change事件(实际接收的父组件callback方法)-----> 父组件callback被调用,父组件的state里的值都发生改变,此时已变成和子组件state里一样的值了 -----> state改变后的值,又通过props传给了子组件Child -----> 再一次渲染出来传过来的值,即和子组件一模一样的值,此时整个过程全部结束。

跨级组件通信

顾名思义就是互不相干且之间隔了好几级的一种通信交流方式。下面先看样例代码:

// 跨级组件通信
import React from "react";

const ThemeContext = React.createContext("light");

class ContextMess extends React.Component {
  static contextType = ThemeContext;
  render() {
    return (
      <ThemeContext.Provider value="dark">
        <div style={{padding: 30+'px'}}>
          <h3>{this.context}</h3>
          <Toolbar></Toolbar>
        </div>
      </ThemeContext.Provider>
    );
  }
}

class Toolbar extends React.Component {
  render() {
    return (
      <div>
        <ThemedButton></ThemedButton>
      </div>
    );
  }
}

class ThemedButton extends React.Component {
  static contextType = ThemeContext;
  render() {
    return (
      <div>
        <h1>{this.context}</h1>
        <ThemeContext.Consumer>
          {value => (<h6>{value}</h6>)}
        </ThemeContext.Consumer>
      </div>
    );
  }
}

export default ContextMess;

从上面代码可以看出,有三个组件,ContextMess ,Toolbar ,ThemedButton ,ContextMess 为最外层组件,依次是Toolbar 组件,再是ThemedButton 组件,逐层嵌套。
代码中主要使用了react中的Context技术点,使用了Context中的以下几个API:React.createContext,Context.Provider,Class.contextType,Context.Consumer。

React.createContext: 创建一个 Context 对象。当 React 渲染一个订阅了这个 Context 对象的组件,这个组件会从组件树中离自身最近的那个匹配的 Provider 中读取到当前的 context 值。

Context.Provider: 每个 Context 对象都会返回一个 Provider React 组件,它允许消费组件订阅 context 的变化;Provider 接收一个 value 属性,传递给消费组件;当 Provider 的 value 值发生变化时,它内部的所有消费组件都会重新渲染。

Class.contextType: (代码中通过 static 来定义静态属性contextType,即组件(class)自己的属性,等同于class.contextType)挂载在 class 上的 contextType 属性会被重赋值为一个由 React.createContext() 创建的 Context 对象。这能让你使用 this.context 来消费最近 Context 上的那个值。你可以在任何生命周期中访问到它,包括 render 函数中。

Context.Consumer: 这里,React 组件也可以订阅到 context 变更。这能让你在函数式组件中完成订阅 context;这需要函数作为子元素(function as a child)这种做法。这个函数接收当前的 context 值,返回一个 React 节点。传递给函数的 value 值等同于往上组件树离这个 context 最近的 Provider 提供的 value 值。如果没有对应的 Provider,value 参数等同于传递给 createContext() 的 defaultValue。

思路: 简单来说,那个‘light’一开始创建的就相当于要在其他组件使用的数据,在 ContextMess 组件中通过使用 contextType 获取 createContext 创建的对象,然后通过this.context来获取值,即“light”;除此之外,使用 Context.Provider API 通过value参数将当前值改为“dark”,然后不使用 props 传值方式,在二级组件中可以看到,并没有使用props接收值,最后在下一级组件通过 Class.contextType 和 this.context 方式读取值,除此之外还使用 Context.Consumer API 来获取最近的那个匹配的context值,即改变后的值“dark”。

具体Context相关知识及API使用请点击:React中Context的学习使用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前言如释重负,好用的技术就应该越来越简单React Hooks 是 React 16.8 从提案转为正式加入的新特性。这个新特性是个非常棒的设计。 可以说对于React 技术栈的发展具分割线一样的意义。讲师在课程提到:之前使用 React 作为主要的前端技术,开发一款网页游戏。在整个游戏的各个模块,Redux ,mobx,以及蚂蚁金服的 ant-design,dva, umi 这些框架或者第三方库都有涉及使用。但是自从了解了Facebook官方提案的 Hooks 特性后,才真正觉得获得了前所未有的解脱。如果你有React开发经验,学习了解 Hooks 后,一定有一种如释重负的轻松感。React 带来了方便也带来了迷茫相信关心 React Hooks 这项新特性的童鞋,很多已经有了一定的 React 开发经验。那么你一定有所体验,React 给我们带来方便的同时,也的确和长久以来的前端开发模式有极大的不同。React 并不需要用继承,而是推荐用嵌套。React 有独特的 jsx 语法。大多数情况 jsx 都使得我们的代码更加简洁了。然而有些时候也给我们带来了一些困扰。 比如数据的传递,逻辑的复用。 react 是一种 mvvm 的设计模式,作为开发者一定要清楚,那些数据是业务数据,那些数据是UI数据。否则你的代码很有可能会陷入混乱局面。大型项目模块化与功能解耦困难在公司项目 App 稍大的时候,我们发现状态提升和只通过 props 进行数据传递。很多时候都很难实现我们的需求。这时无论我们是否清楚的了解,但是状态管理也就是 redux mobx 等,轻易地进入到了公司的项目。我们经过初期的尝试发现状态管理,确实比用纯粹的 React 带来了数据传递上的方便,以及代码组织上的清晰。但前提是你看懂且理解了 redux 大神晦涩的官网文档。 本来 React 被设计用来组件化前端开发。但当我们初期使用状态管理,我们常常会过度的使用状态数据,业务逻辑和ui逻辑没有清楚的分离,最终你的应用代码结果可能是:除了少数几个组件是独立的解耦的,大多数组件都因为状态数据的共享而耦合在了一起,且他们也完全依赖状态管理框架。无法再轻松的转移复用。使用高阶组件,属性渲染,渲染回调等高级特性,确实可以帮我们解决模块或功能的解耦问题。但是这些方法,确实有点超出普通“猿类”的技能。且降低了代码的可读性,对于团队协作,这是很致命的问题。React Hooks 真正开启前端模块化的金钥匙对于以上问题,React Hooks 都有很好的解决方案,官方的设计动机就是解决这些曾经的繁琐,化繁为简。React Hooks 让我们在纯函数就可以使用 React 的众多特性。而不必使用类。代码扁平,易读。解耦状态相关逻辑,UI逻辑和业务逻辑更好的分离。这些逻辑往往是纯函数,而以前很容易混合在类组件。通过自定义 Hooks 我们可以把应用“状态相关”逻辑解耦出来,独立编写到我们自己的hooks 。从而更加易于复用和独立测试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值