【八股系列】react里组件通信有几种方式,分别怎样进行通信?

文章目录

  • [1. props传递(父向子通信):](#1. props传递(父向子通信):)
  • [2. 回调函数作为props(子向父通信):](#2. 回调函数作为props(子向父通信):)
  • [3. Context API:](#3. Context API:)
  • [4. Redux或MobX等状态管理库:](#4. Redux或MobX等状态管理库:)
    • [4.1 Redux使用示例](#4.1 Redux使用示例)
  • [5. refs:](#5. refs:)

1. props传递(父向子通信):

  • 说明 : 父组件通过props属性向子组件传递数据。
  • 如何进行 : 在父组件中定义子组件时,通过属性名将值传给子组件,子组件通过this.props接收。
js 复制代码
// 父组件
import ChildProps from "./ChildProps";
function ParentProps() {
    const message = "我是父组件";
    return <ChildProps message={message} />;
}

export default ParentProps;


// 子组件
function ChildProps(props: any) {
    return (<div>
        <span>{props.message}</span>
        <br />
        <span>我是子组件</span>
    </div>);
}

export default ChildProps;

2. 回调函数作为props(子向父通信):

  • 说明: 子组件通过调用父组件传递的回调函数,将信息传回给父组件。
  • 如何进行 : 父组件定义一个方法,将其作为prop传递给子组件;子组件在适当的时候调用这个函数,传递数据或事件信息。
js 复制代码
// 父组件
import ChildrenEmit from "./ChildrenEmit";
function ParentEmit() {
    const handleButtonClick = (value: string) => {
        console.log(value, "ParentEmit: handleButtonClick");
    };
    return (
        <div>
            <ChildrenEmit onButtonClick={handleButtonClick}></ChildrenEmit>
        </div>
    );
}

export default ParentEmit;


// 子组件
function ChildrenEmit (props: { onButtonClick: (arg0: string) => void; }) {
    return (
        <button onClick={() => props.onButtonClick('按钮被点击了~')}>
            点击
        </button>
    )
}

export default ChildrenEmit;

3. Context API:

  • 说明 : 方式:React提供了一个Context API,允许你在组件树中传递数据,而无需手动逐层传递props
  • 如何使用 :创建一个Context,使用React.createContext();在最顶层的组件中使用<MyContext.Provider value={value}>包裹需要共享状态的组件树;在消费组件中使用<MyContext.Consumer>useContext(MyContext)来访问上下文中的值。
js 复制代码
// MyContext.ts
// 创建Context
import { createContext } from "react";

export const MyContext = createContext('red');
js 复制代码
// ParentContext.tsx
// 父组件
import { useContext } from "react";
import { MyContext } from "./MyContext";
import ChildrenContext from "./ChildrenContext";

const ParentContext = () => {
    const contextValue = useContext(MyContext);

    return (
        <MyContext.Provider value={contextValue}>
            <ChildrenContext />
        </MyContext.Provider>
    );
};

export default ParentContext;
js 复制代码
// ChildrenContext.tsx
// 子组件
import { useContext } from "react";
import { MyContext } from "./MyContext";
import GrandsonContext from "./GrandsonContext";

const ChildrenContext = () => {
    const contentValue = useContext(MyContext);

    return (
        <div>
            <div>子组件颜色: {contentValue}</div>
            <GrandsonContext></GrandsonContext>
        </div>
    );
};
export default ChildrenContext;
js 复制代码
// GrandsonContext.tsx
// 孙组件
import { useContext } from "react";
import { MyContext } from "./MyContext";
import GranddaughterContext from "./GranddaughterContext";

const GrandsonContext = () => {
    const contentValue = useContext(MyContext);

    return (
        <div>
            <div>孙组件1颜色: {contentValue}</div>
            <GranddaughterContext></GranddaughterContext>
        </div>
    );
};

export default GrandsonContext;
js 复制代码
// GranddaughterContext.tsx
// 孙组件
import { useContext } from "react";
import { MyContext } from "./MyContext";

const GranddaughterContext = () => {
    const contentValue = useContext(MyContext);
    return (
        <div>
            <div>孙组件2颜色:{contentValue}</div>
        </div>
    );
};

export default GranddaughterContext;

4. Redux或MobX等状态管理库:

  • 方式 :适用于大型应用,通过将状态提升到一个单一的store中管理,任何组件都可以访问和修改store中的状态。
  • 如何使用 :引入相应的库并设置store,使用Provider组件将store包裹在应用的最外层,组件内部通过connect函数(Redux)Observer(MobX)等与store连接,从而获取或改变状态。

4.1 Redux使用示例

这个例子展示了如何创建一个简单的计数器应用,通过Redux 管理状态。用户点击加减按钮时,会触发actions ,然后通过reducer 更新state ,最终React 组件根据新的state重新渲染。

  • 安装 redux 和 和 react-redux 库。
bash 复制代码
npm install redux react-redux
  • 创建 Action
ts 复制代码
// actions.ts
export const increment = () => {
    return { type: 'INCREMENT' };
  };
  
  export const decrement = () => {
    return { type: 'DECREMENT' };
  };
  • 创建 reducer
ts 复制代码
// reducer.ts
const initialState = { count: 0 };

function counterReducer(state = initialState, action: { type: any; }) {
  switch (action.type) {
    case 'INCREMENT':
      return { ...state, count: state.count + 1 };
    case 'DECREMENT':
      return { ...state, count: state.count - 1 };
    default:
      return state;
  }
}

export default counterReducer;
  • 创建 store
ts 复制代码
// store.ts
import { createStore } from 'redux';
import counterReducer from './reducer';

const store = createStore(counterReducer);

export default store;
  • 创建组件使用
ts 复制代码
import { connect } from 'react-redux';
import { increment, decrement } from './actions';
import { ReactElement, JSXElementConstructor, ReactNode, ReactPortal, MouseEventHandler } from 'react';

function ParentRedux(props: { count: string | number | boolean | ReactElement<any, string | JSXElementConstructor<any>> | Iterable<ReactNode> | ReactPortal | null | undefined; onIncrement: MouseEventHandler<HTMLButtonElement> | undefined; onDecrement: MouseEventHandler<HTMLButtonElement> | undefined; }) {
  return (
    <div>
      <h1>Counter: {props.count}</h1>
      <button onClick={props.onIncrement}>+</button>
      <button onClick={props.onDecrement}>-</button>
    </div>
  );
}

const mapStateToProps = (state: { count: any; }) => ({
  count: state.count,
});

const mapDispatchToProps = (dispatch: (arg0: { type: string; }) => any) => ({
  onIncrement: () => dispatch(increment()),
  onDecrement: () => dispatch(decrement()),
});

export default connect(mapStateToProps, mapDispatchToProps)(ParentRedux);
  • 根组件导入
js 复制代码
import React from "react";
import "./App.css";
import { Provider } from 'react-redux';
import store from './page/redux/store';
import ParentProps from "./page/props/ParentProps";
import ParentEmit from "./page/emit/ParentEmit";
import ParentContext from "./page/context/ParentContext";
import ParentRefs from "./page/refs/ParentRefs";
import ParentRedux from "./page/redux/ParentRedux";

function App() {
    return (
        <div className="App">
            <div className="App-item">
                测试父子传参:<ParentProps></ParentProps>
            </div>
            <div className="App-item">
                测试子传父:<ParentEmit></ParentEmit>
            </div>
            <div className="App-item">
                测试context传参:<ParentContext></ParentContext>
            </div>
            <div className="App-item">
                测试refs传参:<ParentRefs></ParentRefs>
            </div>
            <Provider store={store}>
                <div className="App-item">
                    测试redux传参:<ParentRedux></ParentRedux>
                </div>
            </Provider>
        </div>
    );
}

export default App;

这个例子展示了如何创建一个简单的计数器应用,通过Redux管理状态。用户点击加减按钮时,会触发actions,然后通过reducer更新state,最终React组件根据新的state重新渲染。

5. refs:

  • 方式 :主要用于访问DOM元素或在组件之间传递一个可变的引用。
  • 如何使用 :可以通过React.createRef()创建ref,然后将其附加到特定的React元素上。在组件中,可以通过this.myRef.current访问DOM元素或在类组件间传递ref以直接操作另一个组件的实例。
ts 复制代码
// ParentRefs.tsx
// 父组件
import { useRef } from "react";
import ChildRefs from "./ChildRefs";

const ParentRefs = () => {
    const childRef = useRef<HTMLInputElement>(null);

    const handleClick = (): void => {
        childRef?.current?.focus();
    };

    return (
        <>
            <ChildRefs ref={childRef} />
            <button onClick={handleClick}>Focus Child Input</button>
        </>
    );
};

export default ParentRefs;
ts 复制代码
// ChildRefs.tsx
// 子组件
import { forwardRef } from 'react';

const ChildRefs = forwardRef<HTMLInputElement>((props, ref) => {
    return (
        <div>
            <input type="text" ref={ref} />
        </div>
    );
});

export default ChildRefs;
相关推荐
mldong33 分钟前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排1 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60612 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角3 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!3 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰3 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi5 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen5 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马6 小时前
AI源码分析:拆解模型底层实现逻辑
前端
BillKu6 小时前
全局样式变量:CSS 自定义属性(--border-color)和SCSS 变量($border-color)的说明
javascript·css·scss