React 第九节 组件之间通讯之props 和回调函数

1、父组件向子组件通过 props 进行通讯

首先请先了解组件的三大属性之 props

补充以下内容,基于函数式组件

1.1、单个属性传递

javascript 复制代码
// 父组件
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>
        </>
    )
}
javascript 复制代码
// 子组件
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、多个属性 对象、数组 进行传递

javascript 复制代码
// 父组件
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>
        </>
    )
}
javascript 复制代码
// 子组件
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 设置默认值

这种方式赋默认值,在函数式组件,类式组件中都适用

javascript 复制代码
    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,
    }

在函数式组件中直接给参数添加默认值

这种形式 只适合 函数式组件,并且对于多个参数需要赋默认值的行为,不太友好;

javascript 复制代码
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、子组件通过回调函数向父组件传值

javascript 复制代码
// 父组件
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>
        </>
    )
}
javascript 复制代码
// 子组件 通过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>
    </>
  )
}
相关推荐
崔庆才丨静觅18 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606119 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了19 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅19 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅20 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅20 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment20 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅21 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊21 小时前
jwt介绍
前端
爱敲代码的小鱼21 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax