1、父组件向子组件通过 props 进行通讯
首先请先了解组件的三大属性之 props
补充以下内容,基于函数式组件
1.1、单个属性传递
// 父组件
import { useState } from 'react'
// 引入 ChildA 组件
import ChildA from './childA'
export default function MyComP() {const [name, setName] = useState('Andy')const [age, setAge] = useState(18)const [students, setStudents] = useState([])return (<><h2>父组件</h2>{/* 单个属性传递 */}<ChildA name={name} age={age}></ChildA></>)
}
// 子组件
export default function ChildA(props) {console.log('==data==', props)// 若子组件需要对传入的 props 数据进行再次加工,类似 VUE 中写法,需要使用新的变量接住 props的属性,比如自身名称 需要在父组件名称基础上 +1,如:const [selfName, setSelfName] = useState(props.name)const handleChangeSelfName = () => {setSelfName(`${selfName}+1`)}return (<><h3>childA组件:</h3>{/* 子组件中如果不需要 对props 传递进来的值进行二次加工,则直接展示使用即可 */}<p>操作人员:{props?.name ?? '--'}</p> <p>年龄:{props?.age ?? '--'}</p> <p>子组件自身名称:{setSelfName}</p><button onClick={handleChangeSelfName}>修改自身名称</button></>)
}
1.2、多个属性 对象、数组 进行传递
// 父组件
import { useState } from 'react'
import ChildA from './childA'
export default function MyComP() {const [students, setStudents] = useState([{name: '张三', age:18},{name: '李四', age: 19},{name: '王五', age: 20},])const [useInfo, setUseInfo] = useState({name: 'Andy',age: 18,gender: '男',address: '郑州',})return (<><h2>父组件</h2>{/* 通过扩展运算符,或者将整个数组对象传给子组件 */}<ChildA students={students} useInfo={{...useInfo}}></ChildA></>)
}
// 子组件
import {useState} from 'react'export default function ChildA(props) {console.log('==data==', props)return (<><h3>学生信息:</h3><ul>{props.students.map((student, index) =>{return(<li key={index}><p>姓名:{student.name}</p><p>年龄:{student.age}</p></li>)})}</ul></>)
}
1.3、函数式组件中 默认值的写法
通过 defaultProps 设置默认值
这种方式赋默认值,在函数式组件,类式组件中都适用
import React from 'react'export default function ChildB(props) {return (<><h2>子组件B</h2><p>年龄:{props?.age ?? '--'}</p> <p>子组件操作人员:{props?.name ?? '--'}</p></>)}ChildB.defaultProps = {name: 'ChildB', // 设置默认名称与年龄age: 20,}
在函数式组件中直接给参数添加默认值
这种形式 只适合 函数式组件,并且对于多个参数需要赋默认值的行为,不太友好;
import React from 'react'
export default function ChildB({name='ChildB', age=23}) {return (<><h2>子组件B</h2><p>年龄:{age ?? '--'}</p> <p>子组件操作人员:{name ?? '--'}</p></>)
}
1.4、父组件 通过children 属性 向子组件传 对象 dom结构
知道有这么回事就行,不建议使用,削减了组件的健壮性,
类似vue中插槽
的作用
```javascript
// 父组件
import { useState, useRef, useEffect } from 'react'import ChildB from './childB'
export default function MyComP() {const [name, setName] = useState('Andy')const [useInfo, setUseInfo] = useState({name: 'Andy',age: 18,gender: '男',address: '郑州',})const handleChangNaem = (newName) => {setName(newName)}const handleChangeRef = () => {console.log('---myComRef-',)}return (<><h2>父组件</h2><ChildB onChangName={handleChangNaem} name={name} >{/* 可以传递多种类型,多个节点 */}{/* 向子组件传递额外属性 */}{{...useInfo}}{/* 向子组件传递 dom结构 */}<span>children 数据</span></ChildB></>)
}```
子组件接收 props 的children属性,children是一个数组
```javascript
export default function ChildB({name, onChangName, children}) {console.log('===children=', children)const [text, setText] = useState('')const handleChangNaem = () => {console.log('修改名称')onChangName('Andy222') // 假设修改名称}
return (<div><h2>子组件B</h2><p>子组件操作人员:{name ?? '--'}</p><button onClick={handleChangNaem}>修改名称</button><p>用户信息{children[0].name}</p><p>{children[1]}</p></div>
)
}
```
children 是一个数组,可以通过数组的 map、forEach 方法进行遍历;
父组件传递的数据可以是 基本类型变量、引用类型变量、DOM结构、还可以是函数
注意:空节点(null,undefined 以及布尔值),字符串
,数字
和 React 元素 都会被统计为单个节点。在遍历统计的过程中,React 元素不会被渲染,所以其子节点不会被统计。Fragment 也不会被统计
2、子组件通过回调函数向父组件传值
// 父组件
import { useState } from 'react'
import ChildB from './childB'
export default function MyComP() {const [name, setName] = useState('Andy')const [age, setAge] = useState('18')const handleChangNaem = (newName) => {setName(newName)}return (<><h2>父组件</h2>{/* 父组件 通过 onChangName 函数接收 子组件传递参数 */}<ChildB onChangName={handleChangNaem} name={name}></ChildB></>)
}
// 子组件 通过onChangeName 给父组件传递新名称
export default function ChildB({name='ChildB', age=23, onChangName}) {const handleChangNaem = () => {console.log('修改名称')onChangName('Andy222') // 假设修改名称}return (<><h2>子组件B</h2><p>年龄:{age ?? '--'}</p> <p>子组件操作人员:{name ?? '--'}</p><button onClick={handleChangNaem}>修改名称</button></>)
}