React 组件之间的通信方式

本文详细介绍了组件间的三种通信方式:父-子、子-父及同级组件通信,并通过实例阐述了不同通信方式的具体实现与动机。

在项目开发的过程中,随着应用功能复杂度的增加和组件层次划分的需求,组件之间的通信越来越多,

我大致认为组件之间的通信分为3种:父-子组件通信、子-父组件通信和同级组件之间的通信。

1.父-子组件通信

1.1通信的手段

这是最常见的通信方式,父组件只需要将子组件需要的props传给子组件,子组件直接通过this.props来使用。

1.2 通信内容

更多要提的是如何合理的设置子组件的props,要想将子组件设计成一个复用性强的通用组件,需要将能够复用的部分抽象出来,

抽象出来的props有两种形成,一种是简单的变量,另一种是抽象出来处理某种逻辑的函数。

以Header 组件为例      

 

抽象出来三个props,分别是中间的title,渲染组件左边的renderLeftComponent,渲染组件右边的renderRightComponent

Header的 部分实现

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

renderLeftComponent () {

    let leftDOM = {};

 

    if(this.props.renderLeftComponent) {

        return this.props.renderLeftComponent();

    }

    if (this.props.showBack) {

        let backFunc = this.props.onBack || this.goBack;

        leftDOM = (<a onClick={backFunc.bind(this)}><i className="icon left-icon icon-left-arrow"></i></a>);

    }

    return leftDOM;

}

renderRightComponent () {

    if(this.props.renderRightComponent) {

    return this.props.renderRightComponent();

}

}

render () {

    return (

        <header className="header-wrapper">

            <div className="header header-normal">

            {this.renderLeftComponent()}

            <span>{this.props.title || '美团商超'}</span>

            {this.renderRightComponent()}

            </div>

        </header>

    );

}

 

1.3 通信的动机

1.1中Header组件 props的通信动机 是子组件需要这样的属性来完成自己的展示。还有一种动机可以统称向子组件传递监听事件,

前一种是子组件的需求,后一种更多的是父组件的需求,例如Listview的onEndReached这种属性,触发源是在子组件中,当子组件

的事件被触发或者达到某种状态的时候,调用父组件从属性中传过来的方法。

 

2. 子-父组件通信

2.1 通信的手段

父-子组件通信的手段是通过子组件的props是子组件用父组件的东西,子-父组件通信,是父组件用子组件的东西,肿么用,在开发过程中

暂时没有用到这种情景。我想到的方法就是将传递的内容直接写在子组件上,然后给子组件设置ref,父组件直接通过ref操作子组件的属性。

2.2 通信的内容

子组件的属性

2.3 通信的动机

父组件想要调用子组件的属性

 

3 同级组件之间的通信

同级组件之间的通信,是构建复杂界面的粘合剂,哎呦喂,我好会比喻啊

以生鲜的首页为例:

 

通信1: Listview需要offsetHeight属性,Listview Height的计算公式:window.innerHeight-Banner的Height-Menu的Height,

而Banner和Menu的Height都是需要在其Mount的时候才能计算。

通信2: ListView需要Menu的MenuId,才能够根据MenuId获取sku数据。

 

3.1通信的方式

同级组件之间的通信还是需要通过父组件作为中介,利用多次父-子组件通信,项目中将需要传递的数据放在了父组件的state中,变动时可以自动的同步传递。

将 bannerHeight,menuHeight,MenuId放在state中。

父组件代码示意:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

this.state {

    bannerHeight: 0,

    menuHeight: 0,

    MenuId: 0

}

setBannerHeight(height) {

    this.setState({bannerHeight:height});

}

setMenuHeight(height) {

    this.setState({menuHeight:height});

}

onMenuClick(menuId) {

    this.setState({menuId:menuId});

}

<Banner setBannerHeight={this.setBannerHeight.bind(this)} />

<Menu setMenuHeight={the.setMenuHeight.bind(this)} onMenuClick={this.onMenuClick.bind(this)} />

<SkuList offsetHeight={this.state.bannerHeight + this.state.menuHeight} menuId={this.state.menuId} />

3.2通信的动机

当组件需要的props,不能直接从父组件中获取时,需要父组件作为中介,再与其他的组件进行通信获取。

转载于:https://www.cnblogs.com/520yang/articles/5157418.html

<think>首先,用户的问题是:“我想查找React组件通信的方法 请问React 组件之间通信的常用方式”。这基于系统指令,我需要参考提供的引用内容。 系统指令包括: - 所有行内数学表达式必须使用 $...$ 格式。 - 独立公式使用 $$...$$ 格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,例如 [^1]。 另外,用户可见层要求: - 回答结构清晰,帮助用户逐步解决问题。 - 尽量保证回答真实可靠。 参考的引用内容: - [^1]: 父子组件通信,通过 props 传递数据。 - [^2]: Context API 用于跨组件层级通信。 - [^3]: 状态提升(Lifting State Up)。 - [^4]: Context API 用于共享值。 - [^5]: 事件总线(Event Bus)方式。 用户的问题是关于 React 组件通信的常用方式。我需要基于这些引用构建回答。 结构化回答: 1. **介绍**:简要解释 React 组件通信的重要性。 2. **常用方式**:列出并详细说明每种方式。 - 父子组件通信(通过 props)。 - 状态提升。 - Context API。 - 事件总线。 - 其他方式如 Redux(如果提到)。 3. **总结**:简要比较或建议。 4. **生成相关问题**:在最后添加相关问题。 确保回答清晰、逐步: - 先介绍最简单的方式。 - 逐步到更复杂的场景。 引用标识: - 当引用特定内容时,在段落末尾添加 [^数字]。 - 例如,提到 props 时引用 [^1]。 数学表达式: - 用户问题中没有数学内容,但系统指令要求所有行内数学表达式用 $...$。在回答中,如果有数学表达式(如示例中的公式),但这里可能不需要,除非涉及计算。React 组件通信不涉及数学,所以我应该避免不必要的数学表达式。只在必要时使用。 语言:使用中文。 生成相关问题: - 在回答末尾,添加 "§§相关问题§§" 部分,列出几个相关问题。 最终回答结构: 1. 开头:回应用户问题。 2. 主体:逐步解释各种通信方式。 3. 结尾:总结。 4. §§相关问题§§:列出相关问题。 现在,基于引用: - 父子通信:props [^1]。 - 状态提升: [^3]。 - Context API: [^2], [^4]。 - 事件总线: [^5]。 其他方式:Redux 被提到 [^2],但未详细说明。我可以简要提及。 编写回答: - 使用自然语言。 - 确保真实可靠:基于标准 React 知识。</think>### React 组件通信的常用方式React 应用中,组件通信是构建复杂用户界面的核心需求。React 遵循单向数据流原则,即数据只能从父组件向子组件传递,这确保了数据流动的可预测性和可维护性。组件通信方式多种多样,根据场景的不同,可以选择适合的方法。下面我将逐步介绍几种常用方式,从简单到复杂,帮助你理解如何实现高效通信。这些方式都基于 React 的核心机制,并参考了常见的最佳实践。 #### 1. **父子组件通信(通过 props)** - **原理**:这是最基础的通信方式,父组件通过 props 向子组件传递数据或函数。子组件接收 props 后用于渲染或触发回调。这种方式严格遵循单向数据流,适用于层级较浅的组件关系。 - **示例**: - 父组件向子组件传递数据:父组件在渲染子组件时,通过属性传递数据;子组件通过 `props` 对象访问数据。 - 子组件向父组件通信:父组件通过 props 传递一个回调函数给子组件,子组件调用该函数来通知父组件(例如更新状态)。 - 优点:简单易用,代码清晰,适用于大多数简单场景。 - 缺点:当组件层级较深时,props 逐层传递会变得繁琐(称为“props drilling”问题)。 - 代码示例(基于引用[^1]): ```jsx // 父组件 import React from 'react'; import ChildComponent from './ChildComponent'; function ParentComponent() { const [count, setCount] = React.useState(0); const increment = () => setCount(count + 1); // 回调函数 return ( <div> <ChildComponent count={count} onIncrement={increment} /> </div> ); } export default ParentComponent; // 子组件 import React from 'react'; function ChildComponent(props) { return ( <div> <p>计数: {props.count}</p> <button onClick={props.onIncrement}>增加</button> </div> ); } export default ChildComponent; ``` - 在这个例子中,父组件通过 props 传递 `count` 数据和 `onIncrement` 回调函数,子组件通过按钮点击触发回调[^1]。 #### 2. **状态提升(Lifting State Up)** - **原理**:当多个子组件需要共享同一状态时,可以将状态提升到最近的公共父组件中。父组件通过 props 将状态和更新函数传递给子组件,实现状态同步。这种方式避免了组件间的直接耦合。 - **示例**: - 适用于兄弟组件或紧密相关的组件组。例如,两个输入框需要同步值。 - 优点:保持状态集中管理,易于调试。 - 缺点:如果公共父组件层级太高,可能导致 props 传递冗长。 - 代码示例(基于引用[^3]): ```jsx // 父组件(状态提升) import React from 'react'; import InputA from './InputA'; import InputB from './InputB'; function ParentComponent() { const [value, setValue] = React.useState(''); return ( <div> <InputA value={value} onChange={setValue} /> <InputB value={value} onChange={setValue} /> </div> ); } export default ParentComponent; // 子组件 InputA function InputA(props) { return <input value={props.value} onChange={(e) => props.onChange(e.target.value)} />; } // 子组件 InputB function InputB(props) { return <input value={props.value} onChange={(e) => props.onChange(e.target.value)} />; } ``` - 这里,父组件管理 `value` 状态,并通过 props 传递给两个子组件,确保它们同步更新[^3]。 #### 3. **Context API(跨组件通信)** - **原理**:Context API 提供了一种在组件树中共享数据的方式,无需逐层传递 props。它通过 `Provider` 组件提供数据,`Consumer` 组件或 `useContext` Hook 消费数据。适用于全局状态(如主题、用户信息)。 - **示例**: - 优点:解决深层嵌套组件的 props drilling 问题,代码简洁。 - 缺点:过度使用可能导致组件依赖不透明,不利于复用。 - 代码示例(基于引用[^2]和[^4]): ```jsx // 创建 Context import React from 'react'; const ThemeContext = React.createContext('light'); // 默认值 // 祖先组件(Provider) function App() { return ( <ThemeContext.Provider value="dark"> <Header /> </ThemeContext.Provider> ); } // 子组件(Consumer 方式) function Header() { return ( <ThemeContext.Consumer> {(theme) => <div>当前主题: {theme}</div>} </ThemeContext.Consumer> ); } // 或使用 useContext Hook(函数组件) function Header() { const theme = React.useContext(ThemeContext); return <div>当前主题: {theme}</div>; } ``` - 在这个例子中,`App` 组件通过 `Provider` 提供主题数据,`Header` 组件直接消费,无需中间传递[^2][^4]。 #### 4. **事件总线(Event Bus)** - **原理**:通过自定义事件系统实现任意组件间的通信组件可以订阅(监听)和发布(触发)事件,类似于观察者模式。适用于非父子关系的组件或跨应用模块。 - **示例**: - 优点:灵活,解耦组件。 - 缺点:事件管理复杂,可能引入内存泄漏或调试困难。 - 代码示例(基于引用[^5]): ```jsx // 事件总线模块(eventBus.js) import { EventEmitter } from 'events'; const eventBus = new EventEmitter(); export default eventBus; // 组件 A(发布事件) import React from 'react'; import eventBus from './eventBus'; const ComponentA = () => { const sendMessage = () => { eventBus.emit('message', 'Hello from A'); }; return <button onClick={sendMessage}>发送消息</button>; }; export default ComponentA; // 组件 B(订阅事件) import React, { useEffect } from 'react'; import eventBus from './eventBus'; const ComponentB = () => { useEffect(() => { const handleMessage = (msg) => console.log(msg); eventBus.on('message', handleMessage); return () => eventBus.off('message', handleMessage); // 清理订阅 }, []); return <div>接收消息</div>; }; export default ComponentB; ``` - 这里,`ComponentA` 发布事件,`ComponentB` 监听并处理,实现任意位置通信[^5]。 #### 5. **其他高级方式** - **Redux 或状态管理库**:对于大型应用,可以使用 Redux、MobX 等库集中管理状态。Redux 通过 store 提供全局状态,组件通过 connect 或 useSelector 访问。这基于引用[^2]的提及,但需注意 Redux 更适合复杂状态逻辑。 - **React Hooks(如 useReducer)**:结合 `useReducer` 和 Context 可以创建轻量级状态管理,避免引入外部库。 #### 总结 React 组件通信的核心是保持单向数据流和组件解耦。简单场景优先使用 props 和状态提升;跨层级共享数据用 Context API;复杂事件处理用事件总线;大型应用考虑 Redux。选择方式时,评估组件关系和性能影响。例如,Context API 适合主题切换等全局数据,而 props 适合父子交互。实际开发中,组合使用这些方式能构建高效、可维护的应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值