当我们使用react 开发 封装组件 肯定涉及 子向父传值
我们来直接上代码
来一个子组件
方式一:通过回调函数(最常用)
import React from 'react'
import { Modal } from 'antd'
const CreateModal = (props) => {
const {
modalVisible,
onSubmit,
onCancel,
title = "添加图书",
children,
okText = "确定",
cancelText = "取消",
width = 520,
...restProps
} = props
// 子组件内部的处理函数
const handleSubmit = () => {
// 子组件准备要传递的数据
const childData = {
message: "这是子组件的数据",
timestamp: new Date().getTime(),
customField: "自定义字段"
}
// 调用父组件传递的回调函数,并传递数据
onSubmit(childData)
}
const handleCancel = () => {
const cancelData = {
reason: "用户取消",
time: new Date().toLocaleString()
}
onCancel(cancelData)
}
return (
<Modal
title={title}
open={modalVisible}
onOk={handleSubmit}
onCancel={handleCancel}
okText={okText}
cancelText={cancelText}
width={width}
{...restProps}
>
{children || (
<div>
<p>这里是默认内容</p>
<p>你可以通过 children 属性传入自定义内容</p>
</div>
)}
</Modal>
)
}
export default CreateModal
其实我认为这个 父向子 传值 传方法 其实相对来说 比 vue 好理解 相对来说
onSubmit(childData)
当我们点击确定的时候 就可以 传值 给父组件。父组件绑定这个数据 就好了
<CreateModal
modalVisible={modalVisible}
onSubmit={handleSubmit}
onCancel={handleCancel}
title="自定义标题"
>
{/* 自定义内容 */}
<div>这是自定义的弹窗内容</div>
</CreateModal>
const [modalVisible, setModalVisible] = useState(false)
const openModal = () => {
setModalVisible(true)
}
const handleSubmit = (e) => {
console.log(e, "e")
}
const handleCancel = () => {
}
方式二:使用 forwardRef + useImperativeHandle
子组件
import React, { forwardRef, useImperativeHandle } from 'react'
import { Modal } from 'antd'
const CreateModal = forwardRef((props, ref) => {
const {
modalVisible,
onSubmit,
onCancel,
title = "添加图书",
children,
okText = "确定",
cancelText = "取消",
width = 520,
...restProps
} = props
// 暴露给父组件的方法
useImperativeHandle(ref, () => ({
// 子组件的方法,父组件可以通过 ref 调用
getChildData: () => {
return {
message: "来自子组件的数据",
data: "其他数据"
}
},
// 子组件的其他方法
validateForm: () => {
// 表单验证逻辑
return true
}
}))
const handleSubmit = () => {
onSubmit()
}
const handleCancel = () => {
onCancel()
}
return (
<Modal
title={title}
open={modalVisible}
onOk={handleSubmit}
onCancel={handleCancel}
okText={okText}
cancelText={cancelText}
width={width}
{...restProps}
>
{children}
</Modal>
)
})
export default CreateModal
父组件使用
import React, { useState, useRef } from 'react'
import { Button } from 'antd'
import CreateModal from './CreateModal'
const ParentComponent = () => {
const [modalVisible, setModalVisible] = useState(false)
const modalRef = useRef()
const handleSubmit = () => {
// 通过 ref 获取子组件数据
const childData = modalRef.current?.getChildData()
console.log('子组件数据:', childData)
// 验证表单
const isValid = modalRef.current?.validateForm()
if (isValid) {
setModalVisible(false)
}
}
const handleCancel = () => {
setModalVisible(false)
}
return (
<div>
<Button onClick={() => setModalVisible(true)}>
打开弹窗
</Button>
<CreateModal
ref={modalRef}
modalVisible={modalVisible}
onSubmit={handleSubmit}
onCancel={handleCancel}
/>
</div>
)
}
方式三:使用 Context(适合深层嵌套)
子组件
import React, { createContext, useContext, useState } from 'react'
import { Modal } from 'antd'
// 创建 Context
const ModalContext = createContext()
const CreateModal = (props) => {
const {
modalVisible,
onSubmit,
onCancel,
title = "添加图书",
children,
okText = "确定",
cancelText = "取消",
width = 520,
...restProps
} = props
const [modalData, setModalData] = useState({})
const handleSubmit = () => {
// 传递数据给父组件
onSubmit(modalData)
}
return (
<ModalContext.Provider value={{ modalData, setModalData }}>
<Modal
title={title}
open={modalVisible}
onOk={handleSubmit}
onCancel={onCancel}
okText={okText}
cancelText={cancelText}
width={width}
{...restProps}
>
{children}
</Modal>
</ModalContext.Provider>
)
}
// 在子组件内部使用
const ModalContent = () => {
const { setModalData } = useContext(ModalContext)
const handleInputChange = (e) => {
setModalData(prev => ({
...prev,
inputValue: e.target.value
}))
}
return (
<div>
<input onChange={handleInputChange} placeholder="输入内容" />
</div>
)
}
export { CreateModal, ModalContent }
总结
-
方式一(回调函数):最常用,适合大多数场景
-
方式二(forwardRef):适合需要调用子组件方法的场景
-
方式三(Context):适合深层嵌套组件通信
推荐使用方式一,因为它最符合 React 的数据流理念,代码清晰易懂。