React第九章(组件通信)

server/2024/10/7 18:53:16/

组件通信Props

React 组件使用 props 来互相通信。每个父组件都可以提供 props 给它的子组件,从而将一些信息传递给它。Props 可能会让你想起 HTML 属性,但你可以通过它们传递任何 JavaScript 值,包括对象、数组和函数 以及html 元素,这样可以使我们的组件更加灵活。

例如我们在使用原生html标签时,我们可以为其传递属性,如下

<img  width='500' height='500' alt='xxx' src='xxxxxxx'  />

那在React中,也允许将属性传递给自己编写的组件 如下

export default function App(){return (<Card title='标题1' content='内容'></Card>)
}

父子组件通信

编写一个子组件 Test

const Test = () => {return <div>Test</div>
}
export default Test 

在App.tsx 引入该子组件

import Test from "./components/Test"
function App() {return (<><Test></Test></>)
}export default App

1. 父向子组件传递 props

支持的类型如下:

  • string title={'测试'}
  • number id={1}
  • boolean isGirl={false}
  • null empty={null}
  • undefined empty={undefined}
  • object obj={ { a: 1, b: 2 } }
  • array arr={[1, 2, 3]}
  • function cb={(a: number, b: number) => a + b}
  • JSX.Element element={<div>测试</div>}
function App() {return (<><Testtitle={'测试'}id={1}obj={{ a: 1, b: 2 }}arr={[1, 2, 3]}cb={(a: number, b: number) => a + b}empty={null}element={<div>测试</div>}isGirl={false}></Test></>)
}

子组件接受父组件传递的props

props是一个对象,会作为函数的第一个参数接受传过来的props值

注意:我们需要遵守单向数据流,子组件不能直接修改父组件的props

在React源码中会使用Object.freeze冻结props,限制props的修改。

Object.freeze() 静态方法可以使一个对象被冻结。冻结对象可以防止扩展,并使现有的属性不可写入和不可配置。被冻结的对象不能再被更改:不能添加新的属性,不能移除现有的属性,不能更改它们的可枚举性、可配置性、可写性或值,对象的原型也不能被重新指定

import React from "react"
interface Props {title: stringid: numberobj: {a: numberb: number}arr: number[]cb: (a: number, b: number) => numberempty: nullelement: JSX.Element
}const Test:React.FC<Props> = (props) => {console.log(props)return <div>Test</div>
}export default Test 

2.定义默认值

第一种方式

将属性变为可选的这儿使用title举例 title?: string

然后将props进行解构,定义默认值 {title = '默认标题'}

import React from "react"
interface Props {title?: stringid: numberobj: {a: numberb: number}arr: number[]cb: (a: number, b: number) => numberempty: nullelement: JSX.Element
}const Test:React.FC<Props> = ({title = '默认标题'}) => {return <div>Test</div>
}export default Test 
第二种方式

使用defaultProps进行默认值赋值,最后把defaultProps 和 props 合并,注意顺序要先写defaultProps,再写props 因为props会覆盖defaultProps的值。

import React from "react"
interface Props {title?: stringid: numberobj: {a: numberb: number}arr: number[]cb: (a: number, b: number) => numberempty: nullelement: JSX.Element
}const defaultProps: Partial<Props> = {title: '默认标题',
}const Test: React.FC<Props> = (props) => {const { title } = { ...defaultProps, ...props }return <div>{title}</div>
}export default Test 

3. React.FC

React.FC是函数式组件,是在TS使用的一个范型。FC是Function Component的缩写

React.FC 帮助我们自动推导Props的类型。

注意:在旧版本的React.FC是包含PropsWithChildren这个声明新版本已经没有了

3.props.children 特殊值

这个功能类似于Vue的插槽,直接在子组件内部插入标签会自动一个参数props.children

function App() {return (<><Test><div>123</div></Test></>)
}

子组件使用children属性

在之前的版本children是不需要手动定义的,在18之后改为需要手动定义类型

这样就会把父级的 <div>123</div> 插入子组件的 <div> 里面

import React from "react"
interface Props {children: React.ReactNode //手动声明children
}const Test: React.FC<Props> = (props) => {return <div>{props.children}</div>
}export default Test 
4.子组件给父组件传值

React没有像Vue那样的emit派发事件,所有我们回调函数模拟emit派发事件

父组件传递函数过去,其本质就是录用函数的回调

import Test from "./components/Test"
function App() {const fn = (params:string) => {console.log('子组件触发了 父组件的事件',params)}return (<><Test callback={fn}></Test></>)
}

子组件接受函数,并且在对应的事件调用函数,回调参数回去

import React from "react"
interface Props {callback: (params: string) => voidchildren?: React.ReactNode
}const Test: React.FC<Props> = (props) => {return <div><button onClick={() => props.callback('我见过龙')}>派发事件</button></div>
}export default Test 

兄弟组件通信

定义两个组件放到一起作为兄弟组件,其原理就是发布订阅设计模式,发布订阅已经讲过无数次了这里不在阐述,原生浏览器已经实现了这个模式我们可以直接使用。

如果不想使用原生浏览器,可以使用mitt

mitt文档 https://www.npmjs.com/package/mitt

import Card from "./components/Card"
import Test from "./components/Test"
function App() {return (<><Test></Test><Card></Card></>)
}export default App

第一个兄弟组件 定义事件模型

import React from "react"
const Test: React.FC = (props) => {const event = new Event('on-card') //添加到事件中心const clickTap = () => {console.log(event)event.params = { name: '我见过龙' }window.dispatchEvent(event) //派发事件}return <div><button onClick={clickTap}>派发事件</button></div>
}
//扩充event类型
declare global {interface Event {params: any}
}export default Test 

第二个兄弟组件接受事件

import './index.css'
export default function Test2() {//接受参数window.addEventListener('on-card', (e) => {console.log(e.params, '触发了')})return <div className="card"></div>
}

http://www.ppmy.cn/server/128399.html

相关文章

TryHackMe 第5天 | Pre Security (四)

该学习路径讲解了网络安全入门的必备技术知识&#xff0c;比如计算机网络、网络协议、Linux命令、Windows设置等内容。过去三篇已经对前三块内容进行了简单介绍&#xff0c;本篇博客将记录 Windows设置 部分。 Windows Fundamentals Part 1 对于 Windows &#xff0c;肯定会感…

快手:数据库升级实践,实现PB级数据的高效管理|OceanBase案例

本文作者&#xff1a;胡玉龙&#xff0c;快手技术专家 快手在较初期采用了OceanBase 3.1版本成功替换了多个核心业务、数百套的MySQL集群。至2023年&#xff0c;快手的数据量已突破800TB大关&#xff0c;其中最大集群的数据量更是达到了数百TB级别。为此&#xff0c;快手将数据…

《RabbitMQ篇》Centos7安装RabbitMQ

安装RabbitMQ 安装包网盘下载地址 链接&#xff1a;https://pan.baidu.com/s/1bG_nP0iCdAejkctFp1QztQ?pwd4mlw 先上传安装包到服务器&#xff08;erlang-23.3.4.11-1.el7.x86_64.rpm和rabbitmq-server-3.9.16-1.el7.noarch.rpm&#xff09;然后使用指令安装 # 安装 erlang r…

nacos client 本地缓存问题

问题&#xff1a; nacos 更新了配置文件&#xff0c;更新了以后重新启动还是旧的配置信息。 NACOS版本&#xff1a; 1.1.4 解决&#xff1a; 配置缓存 Nacos Client 会将从 Nacos 服务器获取的配置信息缓存在本地。这样&#xff0c;即使 Nacos 服务器不可用&#xff0c;客…

【含开题报告+文档+PPT+源码】基于SSM + Vue的养老院管理系统【包运行成功】

开题报告 随着社会的发展和经济的进步&#xff0c;人口老龄化问题逐渐凸显。统计数据显示&#xff0c;全球范围内的老龄人口比例正在逐年上升&#xff0c;养老需求也随之增长。养老院作为提供专业养老服务的机构&#xff0c;承担着照料老人、提供医疗保健和社交活动等责任。传…

【Blender Python】1.概述和基础使用

概述 众所周知&#xff0c;Blender是一款开源免费的3D建模软件&#xff08;当然不限于3D建模&#xff09;。在Blender中&#xff0c;可以使用其内置的Python解释器执行Python代码&#xff0c;用于程序化的生成网格以及其他内容。你可以基于此创建Blender插件。 这个系列就是快…

从0学习React(3)

在第一篇文章中&#xff0c;我们对index.tsx文件的每一行代码都做了简单的分析。通过第一篇文章的总结&#xff0c;我也大致知道了index.tsx里的很多语法。而第二篇文章&#xff0c;我对index.tsx文件的框架做了一个大致的分析&#xff0c;通过第二篇文章&#xff0c;我对index…

在Git中操作失误,如何撤回

在 Git 中&#xff0c;撤回操作可以通过多种方式实现&#xff0c;具体取决于你想要撤回的操作类型&#xff08;如提交、暂存、修改等&#xff09;。以下是几种常见场景及其相应的撤回方法&#xff1a; 1. 撤回未暂存的修改 如果你在工作区中进行了更改&#xff0c;但还没有将…