React(10)-组件通信(important)
目录
React单项数据流
1.组件数据源:state/props
【面试】对state和props的理解?
props:
state:
UI视图层:(模板+页面=UI视图层)
2.单向数据流演示
单向数据流
React瀑布流
组件通信( important! )
10种React组件之间通信的方法
组件通信-检查Typechecking with PropTypes
一个组件实现任务列表
多个组件实现任务列表
多组件实现流程:
多组件开发流程:
拆分组件思维逻辑:
0.组件分析
1.数据位置(注意!!)
2.行为位置
3.子组件修改父组件里面的状态
4.组件定义
5.函数组件
6.类组件
React单项数据流
1.组件数据源:state/props
【面试】对state和props的理解?
state/props是组件的数据源
props:
props:是组件对外的接口,组件和组件之间形成组件树,组件树之间数据的传递都依靠的是props.
上层组件的props:具体指数据和方法(props可以传递数据和方法),通过上层组件传递给下一层组件
state:
state:是组件对内的接口,只能对内直接使用,对外使用需要通过属性的方式
state私有的:每个组件都在维护自己的私有状态。
UI视图层:(模板+页面=UI视图层)
视图层变化依据props和state
props或自身state变化=>调用render=>React机制产生DOM重新计算(源码)=>重新渲染=>页面变化
2.单向数据流演示
单向数据流
底层操作顶层的行为,基于props由父传子传递,子组件不能直接改变父类的属性,子类通过父类传递的属性绑定行为可以改变父类的状态。
优点:使数据可控,不混乱
App(根组件)=>C1=>C2=>C3
function C3(props){
console.log("C3",props)
return(
<div>
<h2>C3 Component</h2>
<button onClick={props.click}>button</button>
</div>
)
}
function C2(props){
console.log("C2",props)
return(
<div>
<h2>C2 Component</h2>
//解包,传递所有数据
<C3 {...props}/>
</div>
)
}
function C1(props){
console.log("C1",props)
return(
<div>
<h2>C1 Component</h2>
//解包,传递所有数据
<C2 {...props}/>
</div>
)
}
class App extends React.Component{
//数据
state={name:"jack",age:18,single:false}
//行为方法
handleClick=()=>{
this.setState({single:true})
}
render(){
return(
<div>
<h1>App组件</h1>
<h3>single:{this.state.single?"不单身":"单身"}</h3>
//适用于传递部分数据
{/* <C1 name={this.state.name} age={this.state.age} /> */}
//解包,适用于传递所有数据
//state对内接口,传递数据和行为方法
<C1 {...this.state} click={this.handleClick}>
//添加行为后,传递行为信息
</div>
)
}
}
ReactDOM.render(<App />,document.getElementById("app"))
React瀑布流
多个组件形成组件树(props+state)
组件通信( important! )
10种React组件之间通信的方法https://zhuanlan.zhihu.com/p/326254966
父传子:数据流
子传父:回调函数,context,redux公共状态(把状态抽离单独放置)
组件通信-检查Typechecking with PropTypes
官网:
使用 PropTypes 进行类型检查 – Reacthttps://zh-hans.reactjs.org/docs/typechecking-with-proptypes.html#gatsby-focus-wrapper
React拥有内置的类型检测机制,为组件的props运行类型检测。
PropTypes定义为组件类自身的属性,用以定义prop的类型。在开发模式下,当提供一个不合法的值作为prop时,控制台会出现警告;在产品模式下,为了性能考虑应忽略propTypes
引入库:<script src="../js/prop-types"></script>
class Student extends React.Component{
//和Student.defaultProps效果一样,只不过是不同语法糖
//react自带的,做安检用
static defaultProps={
single:"保密'
}
//引用检查库中带的方法
static propTypes = {
name:PropTypes.string.isRequired,
age:ProTypes.number.isRequired
}
static
constructor(props){
super(props)
console.log(props)
}
render(){
console.log(this.props)
let {name,age} = this.pops
return(
<div>
<ul>name:{name}</ul>
<ul>age:{age}</ul>
<ul>single:{single}</ul>
</div>
)
}
}
//验证:constructor打印props时,已经有single了
说明defaultProps发生在costructor构造函数执行之前
Student.defaultProps={
single:"保密'
}
{/*
//检查
Student.propTypes= {
name:ProtoTypes.string.isRequired
age:ProtoTypes.number.isRequired
}
*/}
const student ={
name:"jack",
age:18
}
ReactDOM.render(<Student {...student}/>,document.getElementById("app"))
一个组件实现任务列表
页面显示:
<div>
<h1>Today Tasks:0</h1>
<!--添加任务-->
<div>
<input type="text" />
<button>add Task</button>
</div>
<!--任务列表-->
<div>
<ul>
<li> 0--eatting--2022/09/03 </li><button>delete</button>
<li> 0--eatting--2022/09/03 </li><button>delete</button>
<li> 0--eatting--2022/09/03 </li><button>delete</button>
</ul>
</div>
</div>
页面重构:
受控组件写法
class App extends React.Component{
//数据
state = {
tasks:[],
task:"",
date:new Date().toLocalDateString()
}
//行为
(1)任务同步:input输入框同步到task
handleChange = (e) => {
console.log(e.target)
this.setState({
task:e.target.value //替换task默认值
},()=>{
console.log("task2",this.state.task)
//解决"state1"打印存在异步问题,添加新的箭头函数作为参数
})
console.log("task1",this.state.task)
//接收不到正确的输入框内内容
原因:setState在合成事件中是异步的,打印的时候还是取的上一次内容
}
(2)添加任务:task放到tasks中
handleAddTask = () =>{
const {task,tasks} = this.state,
//task为空字符串的时候就不用在添加了,return跳出
if(!task){
return
}
tasks.unshift(task) //将task添加到tasks的前面
注:unshift返回新数组长度,不是新数组,直接改变原数组
this.setState({
tasks:tasks
//添加完成后,清空input输入框中内容,使其为空
task:""
date:new Date().toLocalDateString()
},()=>{
console.log(this.state)
})
}
(3)删除任务:tasks删除某个task
handleDelete(index){
const {tasks} = this.state //已经通过bind绑定了this,解决了this指向问题
console.log(index)
//删除操作,原数组发生变化
tasks.splice(index,1)
this.setState({
tasks
})
}
render(){
<div>
<h1>Today Tasks:{this.state.tasks.length}</h1>
<!--添加任务-->
<div>
<input type="text" value={this.state.task} //双向绑定
onChange={this.handleChange}/>
<button onClick={this.handleAddTask}>add Task</button>
</div>
<!--任务列表-->
<div>
<ul>{ this.state.tasks.map((item,index)=>{return(
<li key={index}>
<span>{index+1}--{task}--{this.state.date}</span>
<button onClick={this.handleDelete.bind(this,index)}>delete</button>
</li> ) }) }
</ul>
</div>
</div>
}
}
ReactDOM.render(<App />,document.getElementById("app"))
多个组件实现任务列表
多组件实现流程:
原型=>保真图=>静态页面(html css js)=>react component大组件(视图/行为/数据)=>拆分小组件
多组件开发流程:
- 定义各自组件
- 定义视图 和 组件组合
- 定义数据
- 定义行为
- 组件通信(props=>数据 行为:事件绑定)
拆分组件思维逻辑:
0.组件分析
App组件
--添加组件 AddTask
--列表组件 TaskList
--列表项组件 TaskItem
1.数据位置(注意!!)
数据是某个组件自己需要,直接定义到自己的组件里面
数据是一些组件共同需要,定义在父组件里面,方便调用
2.行为位置
视图=>触发行为=>改变数据=>重新渲染
数据在哪个组件里面,那么修改该数据的行为就在哪个组件里面,方便行为可以直接调用this.setState修改数据
3.子组件修改父组件里面的状态
例如:AddTask / TaskList都需要修改父组件
父组件 - props(methods) - 子组件 [button - 行为 - 父组件的method]
4.组件定义
函数组件和类组件的选择,依据是否有状态
有=>定义为类组件
没有=>定义为函数组件
5.函数组件
函数组件性能更高,函数组件具有纯函数的特点,函数组件主要作用就是渲染页面,不对数据进行操作,又称之为UI组件。
函数组件匈奴呢个更高,优先函数组件。
6.类组件
类组件涉及数据操作比较复杂,所以称之为复杂组件或容器组件
class App extends React.Component{
state = {
tasks : []
}
//添加任务:props传给AddTask
addTask = (task) =>{
const {task} = this.state
if(!task){
return
}
let taskNew = {task:task,date:new Date().toLocaleTimeString()}
tasks.unshift(taskNew )
this.setState({
task:task
})
}
//删除任务:props传给TaskItem
deleteTask=(index)=>{
const {tasks} = this.state
tasks.splice(index,1)
this.setState({
tasks
})
}
render(){
return(
<div>
<h1>Today Tasks:{this.state.tasks.length}</h1>
<AddTask addTask = {this.addTask}/>
<TaskList tasks = {this.state.tasks} deleteTask = {this.deleteTask}/>
</div>
)
}
}
//添加任务
class AddTask extends React.Component{
state = {task:""}
//任务同步
handleChange=(e)=>{
this.setState({
task:e.target.value
})
}
//子组件调用父组件方法添加
handleAddTask=()=>{
const {task} = this.state
if(!task){
return
}
this.props.addTask(task)
//添加完成之后清除input输入框
this.setState({
task:""
})
}
render(){
return(
<div>
<input type="text" value={ths.state.task} onChange={this.handleChange}/>
<button onClick={this.handleAddTask}>add Task</button>
</div>
)
}
}
//任务列表
//没有自己的状态,不需要维护自己的数据,定义为函数组件
function TaskList(props){
//函数组件和类组件传参不同,函数组件是通过props作为参数传递,类组件是通过this.props传递
return(
<ul>
{
props.tasks.map((item,index)=>{
return <TaskItem key={index} key添加在距离数据源最近的地方
index={index} task={item.task} date={item.date} daleteTask={props.daleteTask}>
})
}
<TaskItem />
</ul>
)
}
function TaskItem(props){
function handleDelete(){
props.deleteTask(props.index)
}
//调用父组件删除
return(
<li key={index}>
<span>{props.index+1}--{props.task}--{props.date}</span>
<button onClick={()=>{
props.dleteTask(props.index)
}}>delete</button>
</li>
)
}
React(10)-组件通信(important)相关推荐
- React之组件通信
组件通信无外乎,下面这三种父子组件,子父组件,平行组件(也叫兄弟组件)间的数据传输.下面我们来分别说一下: 父子组件: var Demo=React.createClass({getInitialSt ...
- 一个播放器引发的思考——谈谈React跨组件通信
在我们react项目日常开发中,往往会遇到这样一个问题:如何去实现跨组件通信? 为了更好的理解此问题,接下来我们通过一个简单的栗子说明. 实现一个视频播放器 假设有一个这样的需求,需要我们去实现一个简 ...
- React中组件通信的几种方式
首次发表在个人博客 需要组件之进行通信的几种情况 父组件向子组件通信 子组件向父组件通信 跨级组件通信 没有嵌套关系组件之间的通信 1. 父组件向子组件通信 React数据流动是单向的,父组件向子组件 ...
- (React入门)组件通信
1.父组件向子组件通信 props 父组件直接通过props向子组件传递需要的信息 import React, { Component } from 'react' //子组件 class Child ...
- react父子组件通信
欢迎关注微信公众号:[ 全栈攻略 ] 在 React 中,数据是自顶而下单向流动的,即从父组件到子组件. 所以就存在父子组件之间的通信的必要性了. 父组件.jsx import React from ...
- React兄弟组件通信
1.在父组件定义好回调函数接收组件A传过来的值 // 引入组件 import SonA from "./components/SonA" import SonB from &quo ...
- react父子组件通信案例
父组件:App组件 子组件:Search组件.List组件 案例需求:文本框中输入关键词,点击搜索按钮后,下方列表展示出搜索结果 实现思路: 子组件Search组件向父组件App传递状态(状态包括:是 ...
- React兄弟组件之间通信
兄弟组件之间通信 React是只有单项数据流动模式,也就是只能父组件的数据传递给子组件,而没有办法将子组件的数据传递给父组件.那么如果想要两个子兄弟组件通信该怎么办呢? 答案是可以通过子组件向父组件推 ...
- React组件通信--props
React组件通信 1.props接收数据 //index.js import App from "./App";ReactDOM.render(<App name='传递数 ...
- [react] react兄弟组件如何通信?
[react] react兄弟组件如何通信? 状态提升,通过父组件的state和方法传递到两个子组件 个人简介 我是歌谣,欢迎和大家一起交流前后端知识.放弃很容易, 但坚持一定很酷.欢迎大家一起讨论 ...
最新文章
- 攻读计算机视觉和机器学习硕士给我带来了什么?
- 物料编码原则外部分配还是内部分配
- maven pom配置文件样本
- 藤条生长为字母的动画
- ListString^^ 引用空间
- pycharm运行python程序后显示_pycharm运行和调试不显示结果的解决方法
- python之os.path.join
- python 当前时间增加一个月
- 2021年茶艺师(初级)考试题库及茶艺师(初级)作业考试题库
- 个位数字加百位数字等于千位数字加上十位数字,且该该数为奇数
- Matlab数字图像处理学习记录【9】——表示与描述
- 动态规划旅游问题:汽车加满油可以跑n千米,中途有若干个加油站,请用动态规划的方式求解中途加油次数最少的方案。
- just for save
- m73p黑苹果_ThinkCentre M93z 吃上黑苹果
- java jacob api_jacob使用入门 | 学步园
- 现货黄金赚吗:黄金实战技巧
- ubuntu:更新源操作步骤
- HTTP状态码常见的状态码!
- Xilinx HLS FFT IP核运行时动态配置FFT长度
- 百度网盘和官网下载并安装windows版本的Redis