React中组件通信01------props
- [1. 父传子------props](#1. 父传子——props)
-
- [1.1 简单例子------props](#1.1 简单例子——props)
- [1.2 props 可以传递任何数据](#1.2 props 可以传递任何数据)
-
- [1.2.1 传递数字、对象等](#1.2.1 传递数字、对象等)
- [1.2.2 传递函数](#1.2.2 传递函数)
- [1.2.3 传递模版jsx](#1.2.3 传递模版jsx)
- [2. 子传父 + 子传子------props](#2. 子传父 + 子传子——props)
-
- [2.1 父传子------传递函数](#2.1 父传子——传递函数)
- [2.2 子传父------通过父传子的函数实现](#2.2 子传父——通过父传子的函数实现)
- [2.3 优化 + 子传子(兄弟通信)](#2.3 优化 + 子传子(兄弟通信))
- [3. render props](#3. render props)
-
- [3.1 组件标签上的标签体内容 传递](#3.1 组件标签上的标签体内容 传递)
- [3.2 render props](#3.2 render props)
- [4. 附代码:](#4. 附代码:)
1. 父传子------props
1.1 简单例子------props
- 给子组件标签添加属性,属性名自定义,保持语义化即可。
- 简单例子的核心代码,很简单就先截图吧,代码一起附在最后了,需要注意的是:类式组件与函数式组件的不同,如下:
1.2 props 可以传递任何数据
1.2.1 传递数字、对象等
- 上面我们看到传递的是字符串,下面简单看看传递对象,如下:
1.2.2 传递函数
- 这个详细看下面的 《2. 子传父 + 子传子》,下面有详细的介绍。
1.2.3 传递模版jsx
- 如下:
2. 子传父 + 子传子------props
2.1 父传子------传递函数
- 父传子函数的重要性,主要是下面怎么通过它实现子传父,简单看看父传子传函数,如下:
- 效果如下:
2.2 子传父------通过父传子的函数实现
- 下面需求是在,子组件里添加狗狗数据,并把数据传递给父组件,如下:
- 看效果:
2.3 优化 + 子传子(兄弟通信)
- 下面实现的需求是:在上面子组件D中有一个按钮,点击触发addDog(即:添加新的dog),并在另一个子组件E中有所体现。
- 所以流程就是:父把函数addDog 传递给子组件D,子组件D中在调函数的时候把新增数据传给父,父的addDog中实现更新state数据,然后子组件E中实时展示最新的父中的传来的state数据,具体实现,如下:
- parent.jx,如下:
- D组件如下:
- E组件中就简单了,直接接受父传来的数据即可,如下:
- parent.jx,如下:
- 效果如下:
3. render props
3.1 组件标签上的标签体内容 传递
- 如果要传递组件标签上的标签体内容,获取的时候需要注意,此传递的内容放到了props的children属性上,如下:
- 如果上面的标签体内容放的不是love,而是另外一个组件F,和ChildE形成父子关系的F组件,那依然是放在了props的children属性上,如下:
3.2 render props
-
上面3.1中通过把组件F放在ChildE的标签体内来形成父子关系,可以用另外一种方式实现,就是通过传递箭头函数的方式,如下:
javascript<div className="childE"> <ChildE dogList={this.state.dogList} testJsx={<p>测试一下传递jsx</p>} render={()=><F/>} /> </div>
javascript{props.render()}
-
传参数的情况,这里的函数名习惯用render,所以叫 render props ,如下:
javascript<div className="childE"> <ChildE dogList={this.state.dogList} testJsx={<p>测试一下传递jsx</p>} // render={()=><F/>} render={(kind)=><F petKind={kind}/>} /> </div>
javascript{props.render('狗狗')}
javascript接到E传来的宠物类型是:{props.petKind}
4. 附代码:
-
parent.jsx:
javascriptimport React from "react"; import ChildA from "./ChildA"; import ChildB from "./ChildB"; import ChildC from "./ChildC"; import ChildD from "./ChildD"; import ChildE from "./ChildE"; import F from "./F"; import './index.css' class Parent extends React.Component{ state = { notice:'通知------今天有学生被开除了!', expelledNum:1, student:{name:'张三',age:21,reason:'逃课次数过多'}, citys:['北京','上海','广州','深圳'], dogList:[ {dogName:'麦兜',dogAge:3}, {dogName:'贝塔',dogAge:2}, ] } //给子组件传递的函数 getCityStrs =()=>{ // console.log(this.state.citys); return this.state.citys; } //给子组件传递的带参数函数,参数用来接受子组件在调用函数时给父组件传递的数据 addDog =(dog)=>{ console.log('收到子组件添加的新dog:',dog); //更新 state中 dogList的数据,这样子组件E中展示的数据就是最新的 const dogList = this.state.dogList; //获取旧数据 const newDogList = [...dogList,dog]; console.log(newDogList); this.setState({dogList:newDogList});// 更新state } render(){ return( <div className="parent"> 我是父组件! <div className="childA"> <ChildA notice={'通知------今天放假!'}/> </div> <div className="childB"> <ChildB notice={this.state.notice} expelledNum={this.state.expelledNum} student={this.state.student}/> </div> <div className="childC"> <ChildC getCityStrs={this.getCityStrs}/> </div> <div className="childD"> <ChildD addDog={this.addDog}/> </div> <div className="childE"> <ChildE dogList={this.state.dogList} testJsx={<p>测试一下传递jsx</p>} // render={()=><F/>} render={(kind)=><F petKind={kind}/>} /> </div> </div> ) } } export default Parent;
-
xxxA.jsx
javascriptimport React from "react"; class ChildA extends React.Component{ render(){ return( <div> 我是子组件A!!!------类式组件 <br /><br /> 收到来自于父组件的数据:{this.props.notice} </div> ) } } export default ChildA;
-
xxxB.jsx
javascriptfunction ChildB(props){ // console.log(props); const {name,age,reason} = props.student; return( <div> 我是子组件B!!!------函数组件 <br /><br /> 收到来自于父组件的数据:{props.notice} <br /> 被开除的人数是:{props.expelledNum} <br /> 被开除学生的信息:{name}-{age}-{reason} </div> ) } export default ChildB;
-
xxxC.jsx
javascriptfunction ChildC(props){ // console.log(props); //调用父传过来的函数 获取citys数据 const citys = props.getCityStrs(); // console.log(citys); return( <div> 我是子组件C!!!------函数组件 <br /><br /> 收到父传子的函数,并调用函数获取了数据: { citys.map((city,index)=>{ return <li key={index}>{city}</li> }) } </div> ) } export default ChildC;
-
xxxD.jsx
javascriptfunction ChildD(props){ // console.log(props); const newDog = {dogName:'泡泡',dogAge:7};// 1. 准备要新增的dog数据 const addDog = props.addDog;//2. 获取父组件传递过来的函数 addDog // addDog(newDog); //3. 在子组件中 执行 addDog 函数,并将新增dog传参过去给父组件 return( <div> 我是子组件D!!!------函数组件 <br /> {/* 1. 点击时,再把newDog 传过去 2. 当然,这里如果看着不舒服,也可以把上面3步封装成一个函数,点击时触发新封装的函数 */} <button onClick={()=>addDog(newDog)}>添加狗狗</button> </div> ) } export default ChildD;
-
xxxE.jsx
javascriptfunction ChildE(props){ console.log(props); const dogList = props.dogList; // console.log(dogList); return( <div> 我是子组件E!!!------函数组件 <br /> {props.testJsx} <br /> 展示狗狗信息: <ul> {dogList.map((dog,index)=><li key={index}>{dog.dogName}-{dog.dogAge}</li>)} </ul> <hr /> {/* {props.children} */} {/* {props.render()} */} {props.render('狗狗')} </div> ) } export default ChildE;
-
F.jsx
javascriptfunction F(props){ return( <div> 我是E组件的子组件,我是F!!!------函数组件 <br /> 接到E传来的宠物类型是:{props.petKind} </div> ) } export default F;