React-组件间通信onRef方法
当在子组件中调用onRef函数时,正在调用从父组件传递的函数。this.props.onRef(this)这里的参数指向子组件本身,父组件接收该引用作为第一个参数:onRef = {ref =>(this.child = ref)} 然后它使用this.child保存引用。之后,可以在父组件内访问整个子组件实例,并且可以调用子组件函数。
组件间通信除了props外还有onRef方法,不过React官方文档建议不要过度依赖ref。
1、父子组件都为Class组件
// 父组件
import React, {Component} from 'react';
import Child form "./Child"
export default class Parent extends Component {
onRef = (ref) => {
this.child = ref
}
click = (e) => {
this.child.getData()
}
render() {
return(
<div>
<Child onRef={this.onRef} />
<button onClick={this.click} >调用子组件</button>
</div>
)
}
}
// 子组件
class default Child extends Component {
componentDidMount(){
//必须在这里声明,所以 ref 回调可以引用它
this.props.onRef(this)
}
getData = () => {
// TODO
)
render() {
return (
<div>
// TODO
</div>
)
}
}
2、父组件为Class组件,子组件为Hooks 组件
// 父组件
import React from "react";
export default class Parent extends React.Component {
constructor(props) {
super(props)
}
handleChildMethod = () => {
this.refChild.onChild()
}
// 获取绑定子组件
onRef (ref) {
this.refChild = ref
}
render() {
return (
<div>
<Child
onRef={(ref) => this.onRef(ref)}
></Child>
<Button onClick={this.handleChildMethod}>调用子组件</Button>
</div>
)
}
}
// Hooks 子组件
import React, {useImperativeHandle} from "react";
const Child = (props) => {
const [form] = Form.useForm();
const {} = props
//正常情况下 ref 是不能挂在到函数组件上的,因为函数组件没有实例,
// 但是 useImperativeHandle 为我们提供了一个类似实例的东西。
// 它帮助我们通过 useImperativeHandle 的第 2 个参数,所返回的对象的内容挂载到 父组件的 ref.current 上。
useImperativeHandle(props.onRef, () => ({
// onChild 就是暴露给父组件的方法
onChild: () => {
return form.getFieldsValue()
}
}))
const onReset = () => {
form.resetFields();
};
const onFinish = (values) => {
console.log('Success:', values);
};
const onFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo);
};
return(
<div>
<Form
name={'formName'}
layout="inline"
autoComplete="off"
form={form}
initialValues={{}}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
>
<Form.Item label="姓名" name="name">
<Input allowClear placeholder="请输入"/>
</Form.Item>
<Form.Item>
<Button type="default" onClick={onReset} >清空</Button>
</Form.Item>
</Form>
</div>
)
}
3、父子组件都为Hooks
// 父组件
import {useRef} from 'react';
import ChildRef from './ChildRef'
const Parent = () => {
const child = useRef();
const updateChildState = () => {
// 组件暴露给父组件的方法
console.log(child.current.getVal());
child.current.changeVal(100)
}
return (
<>
<ChildRef ref={child} />
<button onClick={updateChildState}>触发子组件方法</button>
</>
)
}
import React, { useImperativeHandle, forwardRef } from "react"
const Child = (props, ref) => {
const [count, setCount] = useState(0);
useImperativeHandle(ref, () => ({ // 暴露给父组件的方法
getVal,
changeVal
}))
const changeVal = (val) => {
setCount(val)
}
const getVal = () => {
return count
}
return (
<div>我是子组件{count}</div>
)
}
// forwardRef实际上就是当父组件需要得到子组件元素时,可以利用forwardRef来实现
const ChildRef = forwardRef(Child)
4、父组件为Hooks ,子组件为Class
// 父组件
const Parent = () => {
let refChild = {};
const handleChildMethod = () => {
// 调用子组件方法
refChild.setValue(1000);
}
return(
<div>
<h2>我是父组件</h2>
<Button onClick={handleChildMethod}>调用子组件</Button>
<Child onRef={ref => refChild = ref} ></Child>
</div>
)
}
// 子组件
export default class Child extends React.Component {
constructor(props) {
super(props);
this.state = {
value: 0
}
}
componentDidMount() {
this.props.onRef && this.props.onRef(this);
}
setValue = (value) => {
this.setState({
value
})
}
render() {
const {value} = this.state
return (
<div>
<h2>我是子组件 {value}</h2>
</div>
)
}
}