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>
    </>
  )
}
相关推荐
逆旅行天涯15 分钟前
【vitePress】基于github快速添加评论功能(giscus)
前端·github
我有一棵树33 分钟前
style标签没有写lang=“scss“引发的 bug 和反思
前端·bug·scss
陈奕迅本讯1 小时前
HTML5和CSS3拔高
前端·css3·html5
USER_A0012 小时前
JavaScript笔记进阶篇01——作用域、箭头函数、解构赋值
javascript·笔记
画船听雨眠aa2 小时前
vue项目创建与运行(idea)
前端·javascript·vue.js
我想学LINUX2 小时前
【2024年华为OD机试】(C/D卷,200分)- 5G网络建设 (JavaScript&Java & Python&C/C++)
java·c语言·javascript·网络·python·5g·华为od
大码猴2 小时前
用好git的几个命令,领导都夸你干的好~
前端·后端·面试
℡52Hz★2 小时前
如何正确定位前后端bug?
前端·vue.js·vue·bug
学不完了是吧2 小时前
html、js、css实现爱心效果
前端·css·css3