多种 React 组件通信方式实践

更新日期: 2023-11-27阅读: 307标签: 通信

react中,组件之间的通信是一个非常重要的话题。当我们构建复杂的应用程序时,经常需要不同的组件之间共享数据或者进行相互协作。React提供了几种方式来实现跨组件通信,下面我将详细其中几种通信方式,并提供实际的代码示例。

使用 React Context

基于 React Context 实现跨组件通信的一个常见用例是创建一个能够在不同组件间共享和触发行为的上下文。以下是一个简化的例子,展示了如何在 app.tsx 中触发其他组件(例如,一个弹窗组件)中的方法。

1. 创建一个 Context

首先,我们创建一个新的 Context。这个 Context 将包含我们想要在应用中共享的方法。

import React, { createContext, useContext } from 'react';

// 创建 Context
const MyContext = createContext({
  togglePopup: () => {}, // 这是一个示例方法
});

2. 创建一个 Context Provider

接下来,创建一个提供者组件,它将使得在应用的不同部分都能够访问到 Context 中的值。

export const MyProvider = ({ children }) => {
  const togglePopup = () => {
    // 这里实现弹窗的显示隐藏逻辑
    console.log("Toggle Popup called");
  };

  return (
    <MyContext.Provider value={{ togglePopup }}>
      {children}
    </MyContext.Provider>
  );
};

3. 在 app.tsx 中使用 Provider

在 app.tsx 中,用 MyProvider 包裹整个应用,使得任何子组件都能够访问 Context 中的值。

import React from 'react';
import { MyProvider } from './MyProvider'; // 引入刚才创建的 Provider

function App() {
  return (
    <MyProvider>
      {/* 应用的其余部分 */}
    </MyProvider>
  );
}

export default App;

4. 在子组件中使用 Context

最后,在需要的组件中使用这个 Context。例如,如果你有一个弹窗组件,你可以在其中使用这个 Context。

import React, { useContext } from 'react';
import { MyContext } from './MyContext';

const Popup = () => {
  const { togglePopup } = useContext(MyContext);

  return (
    <div>
      {/* 弹窗的内容 */}
      <button onClick={togglePopup}>关闭弹窗</button>
    </div>
  );
};

export default Popup;

在这个例子中我们创建了一个可以在整个应用中共享的 Context。我们定义了一个 togglePopup 方法,并在需要的组件中通过 Context 使用它。这种方式使得跨组件通信变得简单和模块化。

使用自定义事件

使用自定义事件进行组件间通信是一种非常灵活的方法。在 React 中,我们可以使用第三方库,如 mitt 或 eventemitter3 来实现这一机制。下面是一个基于此思想的实现示例。以下是使用 mitt 的示例。mitt 是一个轻量级的事件发射器/监听器库。

1.安装 mitt

使用 npm install mitt 安装事件监听器,然后创建一个 Event 实例,这个实例将在整个应用中共享。

import mitt from 'mitt';

const emitter = mitt();

export default emitter;

2.在 app.tsx 中触发事件

在 app.tsx 中,你可以触发一个自定义事件,这个事件将被其他组件监听和响应。

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

function App() {
  const openPopup = () => {
    emitter.emit('togglePopup', true);
  };

  return (
    <div>
      <button onClick={openPopup}>打开弹窗</button>
      {/* 其他组件 */}
    </div>
  );
}

export default App;

3.在其他组件中监听事件

在你的公共组件(例如一个弹窗组件)中,监听之前在 app.tsx 中触发的事件。

import React, { useEffect, useState } from 'react';
import emitter from './emitter';

const Popup = () => {
  const [isOpen, setIsOpen] = useState(false);

  useEffect(() => {
    const toggleListener = (state) => {
      setIsOpen(state);
    };

    emitter.on('togglePopup', toggleListener);

    return () => {
      emitter.off('togglePopup', toggleListener);
    };
  }, []);

  if (!isOpen) return null;

  return (
    <div>
      {/* 弹窗内容 */}
      <button onClick={() => setIsOpen(false)}>关闭弹窗</button>
    </div>
  );
};

export default Popup;

这个例子展示了如何使用 mitt 来实现跨组件通信。这种方法对于那些不便于通过 props 或 state 进行传递的复杂交互特别有用。它还可以帮助你减少对全局状态管理解决方案的依赖,从而使组件保持更加解耦和可重用。

使用 React Ref

使用 React Ref 实现组件间的方法调用是一种直接且有效的方式,尤其适用于父组件需要直接调用子组件中的方法的场景。以下是一个使用 React Ref 实现的示例。

1.创建子组件并暴露方法

首先,创建一个子组件并使用 useImperativeHandle 与 forwardRef 来暴露特定的方法。

import React, { useImperativeHandle, forwardRef } from 'react';

const Popup = forwardRef((props, ref) => {
  useImperativeHandle(ref, () => ({
    openPopup: () => {
      console.log("弹窗打开");
      // 弹窗打开的逻辑
    },
    closePopup: () => {
      console.log("弹窗关闭");
      // 弹窗关闭的逻辑
    }
  }));

  return (
    <div>这里是弹窗的内容</div>
  );
});

export default Popup;

2.在父组件中使用 Ref 调用方法

接下来,在父组件中创建一个 ref,并将其传递给子组件。然后,使用这个 ref 来调用子组件中的方法。

import React, { useRef } from 'react';
import Popup from './Popup';

function App() {
  const popupRef = useRef();

  const openPopup = () => {
    popupRef.current.openPopup();
  };

  const closePopup = () => {
    popupRef.current.closePopup();
  };

  return (
    <div>
      <button onClick={openPopup}>打开弹窗</button>
      <button onClick={closePopup}>关闭弹窗</button>
      <Popup ref={popupRef} />
    </div>
  );
}

export default App;

使用 React Ref 来调用子组件的方法是一个非常直观和简单的方法,特别适合于需要直接从父组件控制子组件行为的场景。它允许父组件通过 ref 直接访问子组件的实例

使用 Redux 实现组件间通信

Redux 是一种流行的状态管理库,适用于大型 React 应用。通过 Redux,你可以在应用的不同部分共享状态和逻辑。以下是一个简化的例子,展示如何使用 Redux 来更新和访问应用状态。

1.设置 Redux

首先,你需要设置 Redux 的基本元素:store、reducers 和 actions。

// actions.js
export const togglePopup = () => ({
  type: 'TOGGLE_POPUP'
});

// reducer.js
const initialState = {
  isPopupOpen: false
};

export const reducer = (state = initialState, action) => {
  switch (action.type) {
    case 'TOGGLE_POPUP':
      return { ...state, isPopupOpen: !state.isPopupOpen };
    default:
      return state;
  }
};

// store.js
import { createStore } from 'redux';
import { reducer } from './reducer';

export const store = createStore(reducer);

2.在 app.tsx 中使用 Redux

使用 Redux 的 Provider 来包裹你的应用,并在需要的地方通过 dispatch 触发 action。

import React from 'react';
import { Provider } from 'react-redux';
import { store } from './store';
import { togglePopup } from './actions';
import Popup from './Popup';

function App() {
  return (
    <Provider store={store}>
      <button onClick={() => store.dispatch(togglePopup())}>
        切换弹窗状态
      </button>
      <Popup />
    </Provider>
  );
}

export default App;

3.在其他组件中连接 Redux

在需要的组件中使用 connect 函数(或 useSelector 和 useDispatch 钩子)来访问和更新 Redux 的状态。

import React from 'react';
import { connect } from 'react-redux';

const Popup = ({ isPopupOpen }) => {
  if (!isPopupOpen) return null;

  return (
    <div>弹窗内容</div>
  );
};

const mapStateToProps = state => ({
  isPopupOpen: state.isPopupOpen
});

export default connect(mapStateToProps)(Popup);

Redux 提供一个集中的存储,用于管理整个应用的状态。这对于大型应用来说是非常有用的,因为它可以避免状态在多个组件之间的重复传递。Redux 通过将逻辑集中和模块化,提高了代码的维护性和扩展性。且拥有广泛的中间件和生态系统,支持异步操作、日志记录、持久化等高级功能。

使用 Callbacks 实现组件间通信

通过 props 向子组件传递回调函数是 React 中最基本的通信方式之一。

1.在父组件中定义和传递 Callback

import React, { useState } from 'react';
import Popup from './Popup';

function App() {
  const [isPopupOpen, setIsPopupOpen] = useState(false);

  const togglePopup = () => {
    setIsPopupOpen(!isPopupOpen);
  };

  return (
    <div>
      <button onClick={togglePopup}>切换弹窗状态</button>
      <Popup isOpen={isPopupOpen} onClose={togglePopup} />
    </div>
  );
}

export default App;

2.在子组件中使用 Callback

import React from 'react';

const Popup = ({ isOpen, onClose }) => {
  if (!isOpen) return null;

  return (
    <div>
      弹窗内容
      <button onClick={onClose}>关闭</button>
    </div>
  );
};

export default Popup;

对于简单的父子组件通信,使用回调函数是直接且简单的,它避免了引入额外的库或复杂的架构。以保持组件的独立性和可重用性,因为子组件不需要关心状态是如何被管理的,只需关注它如何响应这些回调。

回调方法不需要任何额外的状态管理库或上下文,这使得应用更轻量,减少了依赖和引入的复杂性。对于小型或不太复杂的应用,使用回调进行状态管理通常足够,并且可以避免过度设计。

总结

在 React 中,组件通信是构建动态和交互式用户界面的关键部分。React 提供了多种方式来实现组件之间的通信,本文列举了其中的几种通信方式并提供了代码示例,每种方式都适用于不同的场景和需求。希望这篇文章能够帮助你更好地理解和运用这些技术


看完本文如果觉得有用,记得点个赞支持,收藏起来说不定哪天就用上啦~

专注前端开发,分享前端相关技术干货,公众号:南城大前端(ID: nanchengfe)

来自:https://segmentfault.com/a/1190000044421000

链接: https://www.fly63.com/article/detial/12579

vue.js $emit/$on的用法和理解_vue组件之间数据传输通信

每个 Vue 实例都实现了事件接口vm.$emit( event, arg ) 触发当前实例上的事件;vm.$on( event, fn )监听event事件后运行。实例说明:Vuejs 用$emit与$on来进行兄弟组件之间的数据传输通信,Vuejs 用$emit与$on来进行跨页面之间的数据传输通信

两个浏览器窗口间通信总结

两个浏览器窗口间通信:一个窗口更新localStorage,另一个窗口监听window对象的storage事件来实现通信;所有的WebSocket都监听同一个服务器地址,利用send发送消息,利用onmessage获取消息的变化;借助iframe 或 window.open;HTML5 中的 Web Worker 可以分为两种不同线程类型

前端跨页面通信,你知道哪些方法?

在浏览器中,我们可以同时打开多个Tab页,每个Tab页可以粗略理解为一个“独立”的运行环境,即使是全局对象也不会在多个Tab间共享。然而有些时候,我们希望能在这些“独立”的Tab页面之间同步页面的数据、信息或状态。

Vue组件之间通信的七种方式

使用Vue也有很长一段时间,但是一直以来都没对其组件之间的通信做一个总结,这次就借此总结一下。父子组件之间的通信props和$emit 父组件通过props将数据下发给props

浏览器标签页之间通信的实现

前端开发过程中,总是避免不了要进行前端标签页之间的通信,最经典的例子莫过于音乐播放网站中,当第一次点击播放列表中的歌曲时,它会打开一个新的标签页进行播放,而当在列表中再次点击歌曲播放时

基于 ThinkJS 的 WebSocket 通信详解

我们的项目是基于 ThinkJS + Vue 开发的,最近实现了一个多端实时同步数据的功能,所以想写一篇文章来介绍下如何在 ThinkJS 的项目中利用 WebSocket 实现多端的实时通信。ThinkJS 是基于 Koa 2 开发的企业级 Node.js 服务端框架

Socket是如何通信的?

其实服务器的处理和客户端大同小异,分三个逻辑分支:检索成功,用检索到的Socket来处理接收报文;检索失败,服务器侦听(listen)目的端口,创建全新的Socket服务客户;检索失败,服务器没有侦听目的端口,丢弃处理

vue中使用v-model完成组件间的通信

如何实现两个组件之间的双向传递呢?即,在父组件中修改了值,子组件会立即更新。在子组件中修改了值,父组件中立即更新。vue中有一个很神奇的东西叫v-model,它可以完成我们的需求。

vue父子组件通信高级用法

vue项目的一大亮点就是组件化。使用组件可以极大地提高项目中代码的复用率,减少代码量。但是使用组件最大的难点就是父子组件之间的通信。父组件通过$refs调用子组件的方法。 以上就是父子组件通信的方式

微服务的三种通信方法

在微服务架构的世界中,我们通过一系列服务构建应用。集合中的每项服务都符合以下标准:松散耦合、可维护和可测试、可以独立部署,微服务架构中的每个服务都解决了应用中的业务问题

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!