React组件通讯

组件通讯

组件是一个独立的单元,默认情况下组件只能自己使用自己的数据。在组件化过程中,我们将一个完整的功能拆分成多个组件,便于更好的完成整个应用的功能。

Props

  • 组件本来是封闭的,要接受外部数据应该可以通过Props来实现
  • props的作用:接受传递给组件的数据
  • 传递数据:给组件标签添加属性
  • 接收数据:函数组件通过参数Props接收数据,类组件通过this.props接收数据

函数组件通讯

函数组件

若子组件是函数组件,父组件和子组件之间进行通信的时候,父函数使用属性传递参数,子函数使用函数方法接收props即可。

类组件接收

类组件接收,通过this.props进行访问

import React, {Component} from "react";
import ReactDom from 'react-dom'
import Demo from './Demo'
class App extends Component{render(){return(<div><h1>我是APP组件</h1><Demo car="litter yellow car" money={100}></Demo></div>)}
}ReactDom.render(<App />,document.getElementById('root'))
import {Component} from "react";export default class Demo extends Component{render() {const {car,money} = this.propsreturn (<div><h1>我是Demo组件</h1><p>{car}</p><p>{money}</p></div>)}
}

props特点

  • 可以给组件传递任意类型的数据
  • props是只读的,不允许修改props的数据,单项数据流
  • 注意:在组件中使用的时候,需要把props传递给super(),否则构造函数无法获取到props
import React, {Component} from "react";
import ReactDom from 'react-dom'
import Demo from './Demo'
class App extends Component{state={money:100}render(){return(<div><h1>我是APP组件</h1><button onClick={this.buy}>购买物品</button><Demoname="zs"money={this.state.money}flag={true}fn={()=>{console.log('fn函数')}}list={[1,2,3]}user={{name:'zs',age:1}}></Demo></div>)}buy = () => {this.setState(prevState => ({money: prevState.money - 10}));}}ReactDom.render(<App />,document.getElementById('root'))
// 函数组件
export default function Demo(props){console.log(props)return(<div><h3>我是DEMO组件</h3><div>金钱{props.money}</div></div>)
}

单项数据流,只能由父亲修改子组件参数,子组件只能接收父亲传过来的值,但是子组件不能反向修改父亲的值。

Props特点

  • 可以给组件传递任意类型的数据
  • props是制度的,不允许修改props的数据,单向数据流
  • 注意:在类组件中使用的时候,需要吧props传递给super(),否则构造函数无法访问到props
class Hello extends React.Component{constructor(props){super(props)}render(){return <div>接收到的数据:{this.props.age}</div>}
}

组件之间的三种通讯

父传子

  1. 副组件提供传递的state数据
  2. 给足子组件标签添加属性,值为state中的数据
  3. 子组件中通过props接受副组件中传递的数据

副组件提供数据并且传递给子组件

import React, {Component} from "react";
import ReactDom from 'react-dom'
import Demo from './Demo'
class App extends Component{state={lastName:''}render(){return(<div><h1>我是APP组件</h1><div>配偶:<input type="text" placeholder="请输入配偶的名字" onChange={this.handleChange}/></div><Demo name={this.state.lastName}></Demo></div>)}handleChange = (event) => {this.setState({lastName: event.target.value,});};
}ReactDom.render(<App />,document.getElementById('root'))

子组件

// 函数组件
export default function Demo(props){console.log(props)return(<div><h3>我是DEMO组件</h3><div>金钱{props.name}</div></div>)
}

子传父

思路:利用回调函数,父组件提供回掉,子组件调用,将要传递的数据作为回调函数的参数。

  1. 副组件提供一个回调函数(用于接收数据)
  2. 将该函数作为属性的值,传递给子组件
  3. 子组件通过Props调用回调函数
  4. 将子组件函数作为参数传递给回调函数

父组件提供函数并且传递给字符串

import React, {Component} from "react";
import ReactDom from 'react-dom'
import Demo from './Demo'
class App extends Component{state={lastName:'',childen:''}render(){return(<div><h1>我是APP组件</h1><div>配偶:<input type="text" placeholder="请输入配偶的名字" onChange={this.handleChange}/></div><div>子组件传递数据:{this.state.childen}</div><Demo name={this.state.lastName} changeName={this.changeName}></Demo></div>)}handleChange = (event) => {this.setState({lastName: event.target.value,});};changeName = (name)=>{console.log('fater accept',name)this.setState({childen:name})}
}ReactDom.render(<App />,document.getElementById('root'))

子组件代码

// 函数组件
import {Component} from "react";
export default class Demo extends Component{state = {wife:'',}render() {return(<div><h3>我是DEMO组件</h3><div>金钱{this.props.name}</div><div>配偶的名字:<input type="text" value={this.state.wifi} onChange={this.handleChange}/></div></div>)}handleChange = (e)=>{this.setState({wife:e.target.value})// 传递给父组件this.props.changeName(e.target.value)}
}
// export default function Demo(props){
//
//     console.log(props)
//     return(
//         <div>
//             <h3>我是DEMO组件</h3>
//             <div>金钱{props.name}</div>
//             <div>
//                 配偶的名字:<input type="text"/>
//             </div>
//         </div>
//     )
// }

自己做的一个小Demo

思路:父亲给孩子钱,孩子小费多少钱,然后返还给给父亲多少钱

在这个小Demo中父亲会使用input给孩子钱,孩子在接受到父亲给的钱后去超市花钱然后再找零给父亲。

import React, {Component} from "react";
import ReactDom from 'react-dom'
import Demo from './Demo'
class App extends Component{state={money:'',remain:''}render(){return(<div><h1>我是APP组件父亲组件</h1>给你:<input type="text" onChange={this.handletext}/>应该还给我:{this.state.remain}<Demo givemoney = {this.state.money} remainmoney={this.remainmoney}></Demo></div>)}handletext = (e)=>{this.setState({money:e.target.value})};remainmoney = (speedmoneys)=>{this.setState({remain:this.state.money-speedmoneys})}
}ReactDom.render(<App />,document.getElementById('root'))
// 函数组件
import {Component} from "react";
export default class Demo extends Component{state = {money: '',speedmoneys:''}render() {return(<div><h3>我是DEMO组件</h3><p>我收到了:{this.props.givemoney}</p>我花了:<input type="text" onChange={this.speedmoney}/></div>)}speedmoney = (e)=>{this.setState({speedmoneys:e.target.value})this.props.remainmoney(e.target.value)}
}

兄弟父子

兄弟组件通讯(没有)

  • 将共享状态提升到最近的公共组件中,由公共父组件管理这个状态
  • 思想:状态提升
  • 公共组件的职责:
    • 提供共享状态
    • 提供共享状态的方法
  • 要通讯的子组件只需通过props接收状态或操作状态的方法

状态提升前

提升状态之后

在这里插入图片描述

context组建通讯

import React from 'react';
import ReactDOM from 'react-dom/client';
import Father from './Father';//1.创建组件
//2.使用Provider组件包裹根元素,Provider组件就是最大的根元素const {Provider,Consumer}  = React.createContext()const root = ReactDOM.createRoot(document.getElementById('root'));
class App extends React.Component {state={color:'red'}render() {return (<Provider value={this.state.color}><div><h1>我是APP组件</h1><Father color = {this.state.color}/></div><Consumer>{(value)=>{return <h1 style={{color:value}}>我是Custom组件</h1>}}</Consumer></Provider>
);
}
}
root.render(<App />);

React使用Consumer进行数据共享,直接使用React.createContext进行创建两个包,使用Provide进行数据展示,然后使用Consumer进行数据共享。
但是数据共享过程中Consumer里面需要用到函数进行引用,使用函数引用的方法才可以进行Consumer设置

使用Childer父传子

import React from 'react';
import ReactDOM from 'react-dom/client';
import Header from './head';
import Dialog from './Dialog';const root = ReactDOM.createRoot(document.getElementById('root'));
class App extends React.Component {render() {return (<div><h1>children属性</h1><Header>首页</Header><Header>登陆</Header><Dialog title={<h1>温馨提示</h1>}><input type="text"/><button>登陆</button><button>注册</button></Dialog></div>);}
}
root.render(<App />);

childer可以穿入任意元素,例如button,input等,这里我定义了一个Dialog的组件

import React, {Component} from 'react';class Dialog extends Component {render() {return (<div><h1>Children属性</h1>{this.props.title}  {/* 这里是渲染title */}{this.props.children}  {/* 这里是渲染input */}</div>);}
}export default Dialog;

可以看到我的接收参数只有两个一个是title一个是childern
我的children直接获取父亲节点传过来的所有结构

Props校验

目的:校验接受的props的数据类型,增加组件的健壮性
对于组件来说,props是外来的,无法保证组件使用者传入什么格式的数据
如果传入数据格式不对,可能会导致组件内部报错。
组件的使用者不能明确知道报错原因

import React from 'react';
import ReactDOM from 'react-dom/client';
import Header from './head';
import Dialog from './Dialog';const root = ReactDOM.createRoot(document.getElementById('root'));
class App extends React.Component {render() {return (<div><h1>children属性</h1><Header>首页</Header><Header>登陆</Header><Dialog title={<h1>温馨提示</h1>} list={[1,2,3,4]}><input type="text"/><button>登陆</button><button>注册</button></Dialog></div>);}
}
root.render(<App />);
import React, {Component} from 'react';
import PropTypes from "prop-types";
class Dialog extends Component {render() {return (<div><h1>Children属性</h1>{this.props.title}  {/* 这里是渲染title */}{this.props.children}  {/* 这里是渲染input */}<ul>{this.props.list.map((item)=>(<li key={item}>{item}</li>))}</ul></div>);}
}// 增加校验规则
Dialog.propTypes = {title: PropTypes.string,list: PropTypes.array
}
export default Dialog;

约束规则:
1.常见类型:array,bool,func,number,object
2.React元素类型:element
3.必填项:isRequired
4.特定的结构对象:shape({})

// 增加校验规则
Dialog.propTypes = {title: PropTypes.string.isRequired,list: PropTypes.array
}

默认属性

在未传入Props时生效,有默认属性

Dialog.defaultProps={pageSize:10
}

在使用组件的时候用户不传入该值,给予默认值设置

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Jenkins自动化部署构建说明(8)

Jenkins构建说明 - 20211012 什么是Jenkins? Jenkins 是一款流行的开源持续集成&#xff08;Continuous Integration&#xff09;工具&#xff0c;广泛用于项目开发&#xff0c;具有自动化构建、测试和部署等功能。它是一个自动化的周期性的集成测试过程&#xff0c;从检出代…

基于容器和集群技术的数据自动化采集设计和实现

目标&#xff1a;部署mysql服务容器并使用docker构建包含python爬虫脚本的容器采集数据到mysql数据库。 环境&#xff1a;Centos7、已配置Kubernetes集群及docker。 环境配置请参考以下文章&#xff1a; CentOS7搭建Kubernetes集群 Kubernetes集群信息如下(虚拟机主机名和IP…

流计算之Flink

文章目录 概要有界无界流集群JobManagerTaskManagersTasks 和算子链Task Slots 和资源 小结 概要 Apache Flink 是一个框架和分布式处理引擎&#xff0c;用于在无边界和有边界数据流上进行有状态的计算。Flink 能在所有常见集群环境中运行&#xff0c;并能以内存速度和任意规模…

图解KMP算法

目录 1.最长公共前后缀1.1前缀1.2后缀1.3最长公共前后缀 2、KMP算法过程2.1例子12.2例子22.3Python代码&#xff1a;2.4next数组的计算过程 1.最长公共前后缀 1.1前缀 前缀说的是一个字符串除了最后一个字符以外&#xff0c;所有的子串都算是前缀。 前缀字符串&#xff1a;A…

Linux字符设备驱动中itcol的使用

文章目录 前言一、ioctl二、代码解析2.1 驱动层2.2 应用层 运行结果总结 前言 在Linux字符设备驱动中&#xff0c;ioctl是必须掌握一个函数&#xff0c;其实在软件层面它就是一个函数&#xff0c;但是我愿意称之为强大的硬件控制器&#xff01;在应用中&#xff0c;让我深刻感…

C#常识篇(二)

委托和事件的区别 委托可以认为是对指定签名的函数的引用&#xff0c;通过委托可以实现将函数作为参数传递或者间接调用函数&#xff0c;委托是类型安全的&#xff0c;仅指向与其声明时指定签名相匹配的函数。委托可以分为单播委托和多播委托&#xff0c;二者的区别在于是对单个…

STM32单片机基本原理与应用(九)

SDIO/SD卡实验 实验内容 将SD卡插入实训平台并烧写程序&#xff0c;开机后TFTLCD屏幕上会显示是否成功初始化SD卡并显示SD卡容量。 电路原理图 实验原理 SD卡的通信方式有两种&#xff1a;SPI和SDIO。SD卡有五种寄存器&#xff0c;如下表 SD 卡的指令由 6 个字节组成&…

YOLOv5算法进阶改进(18)— 引入动态蛇形卷积DSConv(ICCV2023 | 用于管状结构分割)

前言:Hello大家好,我是小哥谈。动态蛇形卷积(Dynamic Snake Convolution,简称DSConv)是一种用于图像处理和计算机视觉任务的卷积神经网络(CNN)操作。它是在传统的卷积操作基础上引入了动态蛇形路径的概念,以更好地捕捉图像中的细节和边缘信息。传统的卷积操作是在固定的…

第三节:kafka sarama 遇到Bug?

文章目录 前言一、先上结果二、刨根问底总结 前言 前面两节&#xff0c;我们已经简单应用了sarama的两个类型Client和ClusterAdmin&#xff0c;其中有一个案例是获取集群的ControllerId&#xff0c;但是在后面的测试过程过程中&#xff0c;发现一个问题&#xff0c;返回的Cont…

SpringMVC 学习(四)之获取请求参数

目录 1 通过 HttpServletRequest 获取请求参数 2 通过控制器方法的形参获取请求参数 3 通过 POJO 获取请求参数&#xff08;重点&#xff09; 1 通过 HttpServletRequest 获取请求参数 public String handler1(HttpServletRequest request) <form action"${pageCont…

js:通过input标签或Drag拖拽文件实现浏览器文件上传获取File文件对象

文档 https://developer.mozilla.org/zh-CN/docs/Web/API/Filehttps://developer.mozilla.org/zh-CN/docs/Web/API/HTMLElement/drag_event 通过读取文件可以获取File对象的信息 lastModified: 1707210706000 lastModifiedDate: Tue Feb 06 2024 17:11:46 GMT0800 (中国标准…

力扣--动态规划1027.最长等差数列

思路分析&#xff1a; 使用动态规划的思想&#xff0c;定义二维数组dp&#xff0c;其中dp[i][j]表示以nums[i]为结尾&#xff0c;公差为(j-1000)的等差数列长度。为了适应负数的情况&#xff0c;将公差的范围设为[-1000, 1000]&#xff0c;并且加上1000作为数组索引。 初始化r…

2.23 Day05

#include "mywidget.h" #include "ui_mywidget.h"MyWidget::MyWidget(QWidget *parent): QWidget(parent), ui(new Ui::MyWidget) {ui->setupUi(this);//居中ui->label02->setAlignment(Qt::AlignCenter);ui->Edit1->setAlignment(Qt::Alig…

【Flink精讲】Flink性能调优:内存调优

内存调优 内存模型 JVM 特定内存 JVM 本身使用的内存&#xff0c;包含 JVM 的 metaspace 和 over-head 1&#xff09; JVM metaspace&#xff1a; JVM 元空间 taskmanager.memory.jvm-metaspace.size&#xff0c;默认 256mb 2&#xff09; JVM over-head 执行开销&#xff1…

springboot219基于SpringBoot的网络海鲜市场系统的设计与实现

网络海鲜市场系统的设计与实现 摘 要 计算机网络发展到现在已经好几十年了&#xff0c;在理论上面已经有了很丰富的基础&#xff0c;并且在现实生活中也到处都在使用&#xff0c;可以说&#xff0c;经过几十年的发展&#xff0c;互联网技术已经把地域信息的隔阂给消除了&…

【数据结构和算法初阶(C语言)】空间复杂度(例题剖析一起探究空间如何评价算法)

目录 1.衔接前言-时间复杂度的回顾 2.关于算法复杂度 3.本文主角-空间复杂度 3.1大O的渐进表示方法 4.空间复杂度例题----实际感受空间复杂度 4.1冒泡排序的空间复杂度 4.2计算递归函数的空间复杂度 4.3动态开辟内存版本求斐波那契数列的空间复杂度 4.4&#xff08;…

TMGM外汇开户需要提供以下材料:

TMGM外汇开户需要提供以下材料&#xff1a; 身份证明&#xff1a;通常需要提供有效的身份证明文件&#xff0c;如身份证、护照或驾驶执照等。 居住证明&#xff1a;您需要提供能够证明您居住地址的文件&#xff0c;如水电费账单、房屋租赁合同、居住证明信等。 银行账户信息&a…

【MySQL】探索表结构、数据类型和基本操作

表、记录、字段 数据库的E-R&#xff08;entity-relationship&#xff0c;实体-关系&#xff09;模型中有三个主要概念&#xff1a; 实体集 、 属性 、 关系集 。 一个实体集对应于数据库中的一个表&#xff0c;一个实体则对应于数据库表 中的一行&#xff0c;也称为一条记录。…

数字电路 第三章—第三节(加法器)

一、二进制数的算术运算 1、两数绝对值之间的运算 &#xff08;1&#xff09;二进制数的加减乘除等算术运算的规则和十进制数类似&#xff0c;只是加法运算的规则为“逢二进一”&#xff0c;减法运算的规则为“借一当二”。 &#xff08;2&#xff09;二进制加法&#xff1a…

2024022201-并发控制

并发控制 多事务执行方式 (1)事务串行执行 每个时刻只有一个事务运行&#xff0c;其他事务必须等到这个事务结束以后方能运行不能充分利用系统资源&#xff0c;发挥数据库共享资源的特点 (2)交叉并发方式&#xff08;interleaved concurrency&#xff09; 事务的并行执行是…