React組件間通信

不借助redux等狀態(tài)管理工具的React組件間的通信解決方法

組件通信分類

React組件間通信分為2大類,3種情況:

  • 1)有嵌套關(guān)系的
    • 父->子
    • 子->父
      這里的父通指上級組件,不一定是直屬上級,可跨級
  • 2)無嵌套關(guān)系的
    • 兄弟組件間
    • 無共同上級組件的

父->子(props)

  • 方法一:父組件向子組件傳遞 props,子組件得到 props 后進(jìn)行相應(yīng)的處理。(跨多層組件的時候只需要一層一層傳下去就行)


    image.png
// 父組件 Parent.js:
import React,{ PureComponent } from "react";
import Children from "./Children.js";

export default class Parent extends PureComponent{
  state = {
    title: '父組件',
  }
  outputDesc = () => {
    console.log('父組件向子組件通信,通過props傳遞參數(shù)或者函數(shù)');
  }
  render(){
    const { title } = this.state;
    const childProps = {
      title,
      onOutputDesc: this.outputDesc,
    }
    return(
      <Children {...childProps} />
    )
  }
}
// 子組件 Children.js:
// 界面上會顯示出 【這是子組件獲取到的父組件的title:父組件】
// 點擊控制臺會打印出 【父組件向子組件通信,通過props傳遞參數(shù)或者函數(shù)】
export default class Children extends PureComponent{
  render(){
    const { title, outputDesc } = this.props;
    return(
      <Fragment>
        <p>這是子組件獲取到的父組件的title:{title}</p>
        <button onClick={onOutputDesc}>點擊</button>
      </Fragment>
    )
  }
}

  • 方法二:通過context

使用 React提供的context API(Provider 和 Consumer)
對于方法一,如果要通信的組件間的層次結(jié)構(gòu)很深,中間的每一層組件都要去傳遞 props,增加了復(fù)雜性,并且這些 props 并不是這些中間組件自己所需要的。
當(dāng)組件層次在三層以上時建議使用context,context做的事情就是創(chuàng)建一個上下文對象,并且對外暴露提供者(通常在組件樹中上層的位置)和消費者,在上下文之內(nèi)的所有子組件,
都可以訪問這個上下文環(huán)境之內(nèi)的數(shù)據(jù),并且不用通過props??梢岳斫鉃橛幸粋€集中管理state的對象,并限定了這個對象可訪問的范圍,在范圍之內(nèi)的子組件都能獲取到它內(nèi)部的值。

// context.js
// Provider和Consumer總是成對出現(xiàn)
import React from 'react'
const demoContext = React.createContext();
const demoProvider = demoContext.Provider;
const demoConsumer = demoContext.Consumer;
export demoProvider;
export demoConsumer;

// 父組件
import React from 'react'
import List from './List'
import { demoProvider } from './context'

export default class Todo extends React.PureComponent {
  state = {
      list: [],
  }
  task = React.createRef()
  handleClick = () => {
      const list = [...this.state.list, this.task.current.value];
      this.setState({ list });
      this.task.current.value = '';
  }
  deleteTask = (index) => {
    const { list } = this.state;
    list.splice(index, 1);
    this.setState({ list });
  }
  render() {
    return (
      // 在父(祖先)級組件中把要傳遞內(nèi)容放到value里面
      <demoProvider value={{deleteTask: this.deleteTask}}>
          <input type="text" ref={this.task}/>
          <button onClick={this.handleClick}> 添加 </button>
          <List list={this.state.list} deleteTask={this.deleteTask}/>
      </demoProvider>
    );
  }
}
// 子組件
import React from 'react'
import {demoConsumer} from './context'
export default class List extends React.PureComponent{

  render() {
    const { list } = this.props
    return (
      <demoConsumer>
        // 后代組件中的組件放在Consumer里面, 內(nèi)部是一個函數(shù), 這個函數(shù)接受一個對象作為參數(shù), 參數(shù)是Provider里面提供的值
        {
          ({ deleteTask }) => {
            return list.map((item, index) => {
              return (
                <li key={item}>
                  { item }
                  <button onClick={()=>{deleteTask(index)}}> 刪除 </button>
                </li>
              )
            })
          }
        }
      </demoConsumer>
    );
  }
}

子->父(回調(diào))

父組件將一個函數(shù)作為 props 傳遞給子組件,子組件調(diào)用該回調(diào)函數(shù),向父組件通信。

// 父組件 Parent.js:
import React,{ PureComponent, Fragment } from "react";
import Children from "./Children.js";

export default class Parent extends PureComponent{
  state = {
    description: '',
  }
  handleChangeDesc = (props) => {
    this.setState({description: '子組件向父組件通信,通過回調(diào)傳遞參數(shù): 在子組件中點擊按鈕改變父組件state中的屬性})
  }
  render(){
    const { description } = this.state;
    const childProps = {
      onChangeDesc: this.handleChangeDesc,
    }
    return(
      <Fragment>
        <p>{description}</p>
        <Children {...childProps} />
      </Fragment>
    )
  }
}

// 子組件 Children.js:
// 界面上會顯示出更新后的description值 【子組件向父組件通信,通過回調(diào)傳遞參數(shù): 在子組件中點擊按鈕改變父組件state中的屬性】
export default class Children extends PureComponent{
  changeParentDesc = () => {
    const { onChangeDesc } = this.props;
    onChangeDesc({description: '子組件向父組件通信,通過回調(diào)傳遞參數(shù): 在子組件中點擊按鈕改變父組件state中的屬性'});
  }
  render(){
    const { title, outputDesc } = this.props;
    return(
      <button onClick={this.changeParentDesc}>點擊</button>
    )
  }
}

兄弟組件間

方法一:利用共同的上級組件作為中間人進(jìn)行通信(子1->父->子2)

方法二:通過自定義發(fā)布-訂閱模式的事件實現(xiàn)(以Node.js中events模塊的EventEmitter 類為例,這個會在我的另一篇文章中細(xì)講)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 組件間不同的嵌套關(guān)系,會導(dǎo)致不同的通信方式。常見的有:父組件向子組件通信、子組件向父組件通信、沒有嵌套關(guān)系的組件之...
    南風(fēng)知我意ZD閱讀 1,362評論 0 0
  • 1. 組件間通信1.1.父組件向子組件通信1.2.子組件向父組件通信1.3.跨級組件間通信1.4.無嵌套關(guān)系組件間...
    愛吃芋圓的小w閱讀 469評論 0 2
  • React作為前端的新一代主流框架,因其組件化的思想,徹底革新了前端停留在DOM操作的古老開發(fā)方式。使用React...
    徐丶清風(fēng)閱讀 555評論 0 3
  • 最近學(xué)習(xí)淺嘗則止的學(xué)習(xí)了一下react.js這個UI的框架,react這個庫給我的最大的感覺就是它能夠完全的接管U...
    璀璨天宇閱讀 620評論 0 0
  • 這次用的彩鉛,畫了一個小時。 先用鉛筆打稿,打完后可以用橡皮擦淡,然后用黑筆描邊,我覺得這樣方便上色。
    沉默島主閱讀 824評論 2 20

友情鏈接更多精彩內(nèi)容