React实现父组件调用子组件的两种写法

 更新时间:2024年04月19日 09:23:20   作者:双子座434  
react通信分很多种,比如:父子通信,兄弟通信等等,这里我们就简单说一下父子通信,父子通信分为:父组件调用子组件里面的方法;子组件调用子组件里面的方法,这里我们着重说一下父组件调用子组件,需要的朋友可以参考下

前言

react通信分很多种,比如:父子通信,兄弟通信等等。这里我们就简单说一下父子通信,父子通信分为:父组件调用子组件里面的方法;子组件调用子组件里面的方法。子调父一个porps就可以解决了,这里我们着重说一下父组件调用子组件。废话不多说,直接上代码:

函数式写法:

方法一:

child.js

import React, { useImperativeHandle, forwardRef } from "react";
 
function Child(props, ref) {
  useImperativeHandle(ref, () => {
    return {
      onClick: handleClick,
    }
  });
 
  const handleClick = () => {
    alert('点击了');
  }
 
  return (
    <button>我是按钮</button>
  )
}
 
export default forwardRef(Child);

index.js

import React, { useRef } from "react";
import Child from './child';
 
function Calling() {
  const nRef = useRef();
 
  const handleClick = () => {
    nRef.current.onClick();
  }
 
  return (
    <div>
      <button onClick={handleClick}>点击后调用子组件</button>
      <Child ref={nRef} />
    </div>
  )
}
 
export default Calling;

父调子通过ref,简单来说:使用钩子函数将子组件自定义的方法绑定到ref.current上面。这里用到了三个钩子:useRef、useImperativeHandle, forwardRef。

1.useRef:父组件使用useRef通过参数(这里的参数命名必须为ref)传递给子组件

2.useImperativeHandle:将子组件自定义的函数添加到父组件的ref上,注意这里,第一个参数为ref,第二个参数为对象(也就是父组件中调用的方法或者要取得属性或者值)。

3.forwardRef:将引用的ref传递给子组件,这时子组件接收到的第一个参数是porps,第二个参数是ref。

上面因为传递给子组件的参数为ref关键字,所以子组件里必须要有接收的方法。

方法二:

child.js

import React from "react";
 
function Child(props) {
  const handleClick = () => {
    alert('点击了');
  }
 
  props.nref = {
    onClick: handleClick,
  }
 
  return (
    <button>我是按钮</button>
  )
}
 
export default Child;

index.js

import React from "react";
import Child from './child';
 
function Calling() {
  const nRef = {};
 
  const handleClick = () => {
    nRef.onClick();
  }
 
  return (
    <div>
      <button onClick={handleClick}>点击后调用子组件</button>
      <Child nref={nRef} />
    </div>
  )
}
 
export default Calling;

index.js(解法二)

import React, { useRef } from "react";
import Child from './child';
 
function Calling() {
  const nRef = useRef();
 
  const handleClick = () => {
    nRef.onClick();
  }
 
  return (
    <div>
      <button onClick={handleClick}>点击后调用子组件</button>
      <Child nref={nRef} />
    </div>
  )
}
 
export default Calling;

大家这里注意看方法二的两个index.js文件差异性,无非就是将空对象换成了useRef,为什么要这样写呢,这样写有什么优点吗?当代码量一样的时候,大家就应该思考一件事情:性能。当然,哪个性能好就选择哪个,我对方法二的这两个index文件做了一下对比(实际上就是空对象和useRef的比较),空对象就不用解释过多了:引用类型...;我们着重解释一下useRef:可以帮我们缓存数据,返回一个ref对象,里面的ref.current是用来存储数据的,返回的ref对象不会被重新创建(言外之意就是他爸爸无论渲染多少次,这个对象指向地址永远只有最原始的那个),这里值的变化不会引起组件的重新render,组件不会因为状态的更新而更新(也就是说,组件状态改变了,这里可以保存改变的状态),如果只想要保存状态,不影响视图更新,并且可以同步获取和更新状态的话,建议使用useRef。

大家想一想,如果他爷爷不断渲染,使用 const nRef = {};是不是就会不断的给nRef赋新的地址,之前的地址只有经过一段时间的不使用才会被垃圾回收机制(不懂垃圾回收机制的去翻翻哈)释放掉;而useRef无论他爷爷渲染多少遍,它的地址最终只有一个。

类组件写法:

方法一:

child.js

import React , { Component } from "react"
 
class Child extends Component {
	handleClick = () => {
           alert('点击了');
        }
 
	render(){
		return (<div>子组件</div>);
	}
}

index.js

class Parent extends Component {
	constructor(props) {
	    super(props);
	 	this.Child = React.createRef();
	}
 
	handleOnClick = ()=>{
		this.Child.current.handleClick();
	}
	render(){
		return (<div>
			<button onClick={this.handleOnClick}>click</button>
			<Child ref={this.Child}></Child>	
		</div>);
	}
}

方法二:

child.js

import React , { Component } from "react"
 
class Child extends Component {
        componentDidMount(){
           this.props.onRef && this.props.onRef(this);
	}
 
	handleClick = () => {
           alert('点击了');
        }
 
	render(){
		return (<div>子组件</div>);
	}
}

index.js

class Parent extends Component {
	handleOnClick = ()=>{
		this.Child.current.handleClick();
	}
 
	render(){
		return (<div>
			<button onClick={this.handleOnClick}>click</button>
			<Child onRef={ data => this.Child = data }></Child>	
		</div>);
	}
}

对比一下类组件的两个方法:

方法一:简单易懂,缺点就是:如果子组件中嵌套了高阶组件,那么就无法指向真实的子组件

方法二:写法更简单易懂,粗暴,缺点就是:需要自定义props属性

这里其实还有一个方法三,思路:大家可以利用高阶组件+反向继承实现。

到此这篇关于React实现父组件调用子组件的两种写法的文章就介绍到这了,更多相关React父调子内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • React 无状态组件(Stateless Component) 与高阶组件

    React 无状态组件(Stateless Component) 与高阶组件

    这篇文章主要介绍了React 无状态组件(Stateless Component) 与高阶组件,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  • 详解React组件卸载怎么中止递归方法

    详解React组件卸载怎么中止递归方法

    最近在处理项目代码的时候,出现了一个bug,组件中的方法在组件卸载后仍然在执行,代码片段发给我看,但是变量的用意我也不懂,只看到有方法调用自身方法,这不就是递归嘛,所以本文详细给大家介绍了React组件卸载怎么中止递归方法,需要的朋友可以参考下
    2024-01-01
  • React中updateContainerImpl方法更新容器源码解析

    React中updateContainerImpl方法更新容器源码解析

    updateContainerImpl方法是React中更新容器的核心方法,负责创建和调度更新,通过createUpdate方法创建更新对象,并通过enqueueUpdate方法将其加入Fiber节点的更新队列,本文介绍React中updateContainerImpl方法更新容器源码分析,感兴趣的朋友一起看看吧
    2026-01-01
  • React 自动聚焦字段使用详解

    React 自动聚焦字段使用详解

    这篇文章主要为大家介绍了React 自动聚焦字段使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • react native带索引的城市列表组件的实例代码

    react native带索引的城市列表组件的实例代码

    本篇文章主要介绍了react-native城市列表组件的实例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • 详解基于webpack搭建react运行环境

    详解基于webpack搭建react运行环境

    本篇文章主要介绍了详解基于webpack搭建react运行环境,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • react项目使用redux初始化方式

    react项目使用redux初始化方式

    这篇文章主要介绍了react项目使用redux初始化方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • react路由中Suspense的详细介绍

    react路由中Suspense的详细介绍

    AppRouter这个组件是一个在现代 React 应用中非常常见的模式,特别是在使用 React Router v6+ 进行路由管理和结合代码分割(Code Splitting)来优化性能时,这篇文章主要介绍了react路由中Suspense的详细介绍,本文给大家介绍的非常详细,感兴趣的朋友一起看看吧
    2025-05-05
  • react简单实现防抖和节流

    react简单实现防抖和节流

    在日常开发中,我们经常会有防抖和节流的需要,可以减小服务器端压力,提升用户体验,本文就详细的介绍了react简单实现防抖和节流,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-05-05
  • React弹窗使用方式NiceModal重新思考

    React弹窗使用方式NiceModal重新思考

    这篇文章主要为大家介绍了React弹窗使用方式NiceModal重新思考分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08

最新评论