【React】组件通信

组件通信

父传子 - props

function Article(props) {
    return (
        <div>
            <h2>{props.title}</h2>
            <p>{props.content}</p>
            <p>状态: {props.active ? '显示' : '隐藏'}</p>
        </div>
    )
}
// 设置默认值方式一
// 使用 defaultProps 设置默认值,当没有父组件的值传入时使用默认值
Article.defaultProps = {
	title: '默认title',
	content: '默认content'
	// ...
}

function App() {

    return (
        <>
            <Article title="标题1" content="内容1" active/>
            <Article title="标题2" content="内容2"/>
        </>
    );
}

export default App;

设置默认值方式二:props 也可以 直接解构并且赋予默认值 比如:{title=“默认标题”}

// 设置默认值方式三:
// 设置默认值也可以写为,作为类的一个静态属性:
static Article.defaultProps = {
	title: '默认title',
	content: '默认content'
	// ...
}

设置默认值方式四:

在这里插入图片描述

参数类型声明一:直接使用 : 的形式进行类型声明。

参数类型声明而:也可以写成箭头函数的形式进行泛型类型声明:

const SmallPage:React.FC<Props> = (props) => {
    
}

该泛型会透传给函数式组件的第一个参数,作为第一个参数的类型。

父传子 - 插槽

function Article({children, title, footer=<div>默认底部</div>}) {
    return (
        <>
            <h1>{title}</h1>
            <div>
                {children}
            </div>
            {footer}
        </>
    )
}

function App() {

    return (
        <>
            <Article title="文章1" footer={<p>这是底部内容1</p>}>
                <h2>标题1</h2>
                <p>内容1</p>
            </Article>
            <Article title="文章2" footer={<p>这是底部内容2</p>}>
                <h2>标题2</h2>
                <p>内容2</p>
            </Article>
        </>
    );
}

export default App;

在这里插入图片描述

子传父 - 自定义事件

子传父 => 状态提升

import {useState} from "react";

function Detail({onActive}) {
    const [status, setStatus] = useState(false)

    function handleClick() {
        setStatus(!status)
        onActive(status)
    }

    return (
        <div>
            <button onClick={handleClick}>点击</button>
            <p style={{
                display: status ? 'block' : 'none'
            }}>Detail 的内容</p>
        </div>
    )
}

function App() {
    const handleActive = (status) => {
        console.log(status)
    }

    return (
        <>
            {/* 父组件接收子组件通过自定义事件 */}
            <Detail
                onActive={handleActive}
            />
        </>
    );
}

export default App;

兄弟组件通信

主要就是使用了发布订阅模式。

// 1. 组件一创建自定义事件
const event = new Event('on-card')
// 2. 组件一创建一个点击事件 触发自定义事件的派发
const clickTap = () => {
    event.params = {data: '我是自定义事件的参数'}
    window.dispatchEvent(event)
}
// 注:使用自定义事件的参数 需要在组件一 扩充声明
declare global {
    interface Event {
        params: {data: string}
    }
}

// 3. 组件二监听自定义事件
// 这个一般会执行两次试因为 react 的严格模式 在 main.tsx 中删掉 StrictMode 标签即可
window.addEventListener('on-card', (event) => {
    console.log('自定义事件触发了', event.params)
})

除了这种方式之外,还可以使用 mitt (在 vue 和 react 中都可以使用)。

多层级通信 - useContext

官方文档:useContext

用法:

  1. createContext 创建一个上下文对象 MyContext 并返回
  2. 组件内传递。可以通过将上下文对象 MyContext 传给 useContext() 来读取上下文的值(比如下面的 2 )
    在这里插入图片描述
  3. 组件间传递。在顶层组件 MyContext.Provider 组件提供数据,在底层组件 useContext 钩子获取消费数据
import {createContext, useContext, useState} from "react";

function Section({children}) {
 	// 2.  顶层组件 MyContext.Provider 组件提供数据
    const level = useContext(LevelContent)
    return (
        <section className="section">
            {/*逐渐从上层提供的LevelContext中取值*/}
            <LevelContent.Provider value={level + 1}>
                {/*children 也就是 heading 需要使用 useContext*/}
                {children}
            </LevelContent.Provider>
        </section>
    );
}

function Heading({children}) {
	// 3. 底层组件 useContext 钩子获取消费数据
    const level = useContext(LevelContent)
    switch (level) {
        case 1:
            return <h1>{children}</h1>;
        case 2:
            return <h2>{children}</h2>;
        case 3:
            return <h3>{children}</h3>;
        case 4:
            return <h4>{children}</h4>;
        case 5:
            return <h5>{children}</h5>;
        case 6:
            return <h6>{children}</h6>;
        default:
            throw Error('未知的 level:' + level);
    }
}
//  1. createContext 创建一个上下文对象
const LevelContent = createContext(0)

function App() {
    return (
        <Section>
            <Heading>主标题</Heading>
            <Section>
                <Heading>副标题</Heading>
                <Heading>副标题</Heading>
                <Heading>副标题</Heading>
                <Section>
                    <Heading>子标题</Heading>
                    <Heading>子标题</Heading>
                    <Heading>子标题</Heading>
                    <Section>
                        <Heading>子子标题</Heading>
                        <Heading>子子标题</Heading>
                        <Heading>子子标题</Heading>
                    </Section>
                </Section>
            </Section>
        </Section>
    )
}

export default App;

在这里插入图片描述

组件通信小案例 - 汇率转换:

App.jsx

import React, {Component} from 'react';
import Money from "./components/Money";

class App extends Component {
    state = {
        dollar: '',
        rmb: ''
    }
    transformToRMB = (value) => {
        if (parseFloat(value) || value === "" || parseFloat(value) === 0) {
            this.setState({
                dollar: value,
                rmb: value === "" ? "" : (value * 7.3255).toFixed(2)
            })
        } else {
            alert('请输入数字')
        }
    }
    transformToDollar = (value) => {
        if (parseFloat(value) || value === "" || parseFloat(value) === 0) {
            this.setState({
                dollar:  value === "" ? "" : (value / 7.3255).toFixed(2),
                rmb: value
            })
        } else {
            alert('请输入数字')
        }
    }

    render() {
        return (
            <div>
                <Money text="美元" money={this.state.dollar} transform={this.transformToRMB}/>
                <Money text="人民币" money={this.state.rmb} transform={this.transformToDollar}/>
            </div>
        );
    }
}

export default App;

Money.jsx

import React from 'react';

function Money(props) {
    const handleChange = (e) => {
        // 将子组件的值传递给父组件 e.target.value 获取输入框的值
        props.transform(e.target.value)
    }
    return (
        <>
            <fieldset>
                <legend>{props.text}</legend>
                <input type="text" value={props.money} onChange={handleChange}/>
            </fieldset>
        </>
    );
}

export default Money;

在这里插入图片描述

受控组件,本质上其实就是将表单中的控件和视图模型(状态)进行绑定,之后都是针对状态进行操作。

案例:

  • 一个基本的受控组件
  • 对用户输入的内容进行限制
  • 文本域
  • 单选与多选框
  • 下拉列表

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/969639.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Tomcat添加到Windows系统服务中,服务名称带空格

要将Tomcat添加到Windows系统服务中&#xff0c;可以通过Tomcat安装目录中“\bin\service.bat”来完成&#xff0c;如果目录中没有service.bat&#xff0c;则需要使用其它方法。 打到CMD命令行窗口&#xff0c;通过cd命令跳转到Tomcat安装目录的“\bin\”目录&#xff0c;然后执…

基于Python深度学习的【蘑菇识别】系统~卷积神经网络+TensorFlow+图像识别+人工智能

一、介绍 蘑菇识别系统&#xff0c;本系统使用Python作为主要开发语言&#xff0c;基于TensorFlow搭建卷积神经网络算法&#xff0c;并收集了9种常见的蘑菇种类数据集【“香菇&#xff08;Agaricus&#xff09;”, “毒鹅膏菌&#xff08;Amanita&#xff09;”, “牛肝菌&…

124 巨坑uni-app踩坑事件 uniCloud本地调试服务启动失败

1.事情是这样的 事情是这样的&#xff0c;我上午在运行项目的时候还是好好的&#xff0c;我什么都没干&#xff0c;没动代码&#xff0c;没更新&#xff0c;就啥也没干&#xff0c;代码我也还原成好好的之前的样子&#xff0c;就报这个错&#xff0c;但是我之前没用过这个服务呀…

Android Studio “Sync project with Gradle Files”按钮消失——文件层级打开不对

问题出现的背景 Android Studio显示&#xff0c;后来查找解决方案&#xff0c;里面提到“Sync project with Gradle Files”按钮&#xff0c;一检查发现自己的软件上面没有这个选项&#xff0c;于是参考 https://debugah.com/android-studio-can-not-find-sync-project-with-g…

什么是HTTP Error 429以及如何修复

为了有效管理服务器资源并确保所有用户都可以访问&#xff0c;主机提供商一般都会对主机的请求发送速度上做限制&#xff0c;一旦用户在规定时间内向服务器发送的请求超过了允许的限额&#xff0c;就可能会出现429错误。 例如&#xff0c;一个API允许每个用户每小时发送100个请…

LAWS是典型的人机环境系统

致命性自主武器系统&#xff08;Lethal Autonomous Weapons Systems&#xff0c;LAWS&#xff09;是一种典型的人机环境系统&#xff0c;它通过高度集成的传感器、算法和武器平台&#xff0c;在复杂的战场环境中自主执行任务。LAWS能够自主感知环境、识别目标、做出决策并实施攻…

IC-Portrait:打造逼真个性化肖像的新纪元!

在数字内容创作、虚拟形象、游戏和增强现实等领域&#xff0c;肖像生成已成为计算机图形学研究的热点。尽管近年来肖像生成模型取得了显著进展&#xff0c;能够生成越来越逼真和吸引人的肖像&#xff0c;但仍面临诸多挑战。 今天&#xff0c;给大家介绍一种个性化肖像生成框架I…

ubuntu服务器部署

关闭欢迎消息 服务器安装好 ubuntu 系统后&#xff0c;进行终端登录&#xff0c;会显示出很多的欢迎消息 通过在用户的根目录下执行 touch .hushlogin 命令&#xff0c;再次登录终端就不会出现欢迎消息 修改hostname显示 修改 /etc/hostname 文件内容为主机名&#xff0c;保…

【第3章:卷积神经网络(CNN)——3.5 CIFAR-10图像分类】

嘿,小伙伴们,今天咱们来聊聊一个超级酷炫的话题——卷积神经网络(CNN)及其在CIFAR-10图像分类中的应用。这不仅仅是一个技术话题,更是一场探索人工智能奥秘的旅程。准备好了吗?咱们这就发车! 一、CNN:人工智能的“千里眼” 首先,咱们得知道CNN是啥。CNN,全名Convol…

腿足机器人之二- 运动控制概览

腿足机器人之二运动控制概览 高层运动规划MPCRL 中层逆运动学和逆动力学底层执行器控制传感器校正 上一篇博客是腿足机器人的骨架和关节的机械和电气组件&#xff0c;关节不仅需要通过机械设计实现复杂的运动能力&#xff0c;还必须通过电子组件和控制系统来精确控制这些运动。…

无人机信号调制技术原理

一、调制技术的必要性 频谱搬移&#xff1a;将低频的基带信号搬移到高频的载波上&#xff0c;便于天线辐射和传播。 信道复用&#xff1a; 利用不同的载波频率或调制方式&#xff0c;实现多路信号同时传输&#xff0c;提高信道利用率。 抗干扰&#xff1a; 通过选择合适的调…

Python 闭包与装饰器

前言&#xff1a;之前讲完了面向对象的三大特征&#xff0c;这篇讲解的是闭包与装饰器&#xff08;作用域&#xff0c;nonlocal关键字&#xff0c;global关键字&#xff09; 闭包 定义 闭包是指有权访问另一个函数作用域中变量的函数。简单来说&#xff0c;即使该函数已经执行…

【Flink快速入门-4.流处理之基于 Key 的算子】

流处理之基于 Key 的算子 实验介绍 在 SQL 中我们经常会用到分组&#xff08;group by&#xff09;操作&#xff0c;在 group 关键词之后指定要聚合的键&#xff0c;在 group 之前指定要聚合的逻辑&#xff08;计数、求和、求最大值等&#xff09;&#xff0c;通过分区键将数…

sib报错:com.*.xctrunner is not in your device!

1、问题描述 在使用sonic集成IOS设备的时候,我们需要通过sonic-agent服务去识别IOS设备。但是在识别的时候提示如下问题: 本质就是在你这个设备中找不到这个设备也就是找不到WebDriverAgentRunner,但是确实安装了,甚至appium可以正常的调用。 或执行如下命令的时候报错:…

数据结构与算法-队列

参考学习&#xff1a;B站-逊哥带你学编程 队列的定义与实现 队列的顺序结构实现 #define MAXSIZE 100 typedef int ElemType;typedef struct {ElemType data[MAXSIZE];int front;int rear; }Queue;图示&#xff1a; 队列的顺序结构-初始化 void initQueue(Queue *Q) {Q->…

SQL联合查询

文章目录 MySQL系列&#xff1a;1.内连接2.外连接3.自连接4.子查询5.合并查询6.插入查询 MySQL系列&#xff1a; 初识MySQL&#xff0c;MySQL常用数据类型和表的操作&#xff0c;增删改查(CRUD)操作(总),数据库约束数据库设计 #班级表 drop table if exists class; create ta…

急停信号的含义

前言&#xff1a; 大家好&#xff0c;我是上位机马工&#xff0c;硕士毕业4年年入40万&#xff0c;目前在一家自动化公司担任软件经理&#xff0c;从事C#上位机软件开发8年以上&#xff01;我们在开发C#的运动控制程序的时候&#xff0c;一个必要的步骤就是确认设备按钮的急停…

哈希表-三数之和

代码随想录-刷题笔记 15. 三数之和 - 力扣&#xff08;LeetCode&#xff09; 内容&#xff1a; 这道题讲真真挺有意思的。双指针的用法很巧妙&#xff0c;而且去重的细节多到离谱。 哈希表本身的做法我没搞懂&#xff0c;而且确实复杂的很。既然有更好的方法就一步到位 本…

边缘计算网关功能优势及带来的数据处理变化

边缘计算是一种分布式计算架构&#xff0c;其核心思想是将数据处理、存储和服务功能移近数据产生的边缘位置&#xff0c;即接近数据源和用户的位置&#xff0c;而不是依赖中心化的数据中心或云计算平台。这种计算模式通过在靠近终端设备的位置进行数据处理&#xff0c;旨在降低…

8D系统与FMEA系统软件的关联性分析

8D系统与FMEA系统的关联性分析 在质量管理中&#xff0c;8D和FMEA是两种重要的工具&#xff0c;它们在功能上相互补充&#xff0c;形成了一个高效的质量管理闭环。 FMEA&#xff08;潜在失效模式及后果分析&#xff09; 是一种预防性工具&#xff0c;用于在产品设计和制造过程…