react函数式组件之兄弟组件中的方法互相调用

2023-10-27

最新更新时间:2022年01月15日14:40:31
《猛戳-查看我的博客地图-总有你意想不到的惊喜》

本文内容:一个父组件和两个子组件,三个组件都是函数式组件,子组件1需要调用子组件2的方法,同时子组件2需要调用子组件1的方法

技术方案分析

兄弟组件的方法互调
  • 子组件1 -> 父组件 -> 子组件2

子组件1通过props调用父组件的方法,父组件通过ref2调用子组件2的方法

  • 子组件2 -> 父组件 -> 子组件1

子组件2通过props调用父组件的方法,父组件通过ref1调用子组件1的方法

父组件调用子组件的方法
  • 父组件通过ref获取子组件实例,然后再调用方法
  • 子组件需要用到两个hooks,forwardRef和useImperativeHandle
  • forwardRef,用户 转发refs到DOM组件 和 在高阶组件中转发refs
  • useImperativeHandle可以让你在使用ref时自定义暴露给父组件的实例值。useImperativeHandle应当和forwardRef配合使用
获取通过Form.create()()创建的函数式组件的实例
  • 通过子组件的wrappedComponentRef属性传递ref
获取被connect包裹的函数式组件的实例
  • 通过forwardRef包裹connect

注意:被withRouter、connect、Form.create等方法包裹的组件并不能抛出ref,需要使用forwardRef抛出子组件的ref

示例代码

父元素
import React, {useRef} from 'react'

import Child1 form '../child1';
import Child2 form '../child2';

function Parent(props){
	const child1Ref = useRef(null);
	const child2Ref = useRef(null);
	
	const child1CallChild2 = ()=>{
		console.log('父元素调用子元素2的方法')
		child2Ref.current && child2Ref.parentCallChild2()
	}
	const child2CallChild1 = ()=>{
		console.log('父元素调用子元素1的方法')
		child1Ref.current && child1Ref.parentCallChild1()
	}
	
	return <div>
		<Child1 wrappedComponentRef={child1Ref} child1CallChild2={child1CallChild2}/>
		<Child2 ref={child2Ref} child2CallChild1={child2CallChild1} />
	</div>
}
export default Parent
子元素1
  • 通过Form.create()(Component)创建的函数式组件,对外暴露实例和方法
import React, {forwardRef, useImperativeHandle} from 'react'
import {Form} from 'antd'

function Child1(props, ref){
	function parentCallChild1(){
		console.log('父组件调用子组件1的方法')
	}
	function c1Callc2(){
		console.log('兄弟元素通信 子组件1调用子组件2的方法')
		props.child1CallChild2()
	}
	// 将parentCallChild1方法暴露给父组件获取的实例
	useImperativeHandle(ref,()=>({parentCallChild1}))
	
	return <div onClick={this.c1Callc2}>
		<Form></Form>
	</div>
}

const FormComponentWrap = Form.create()(forwardRef(Child1))
export default FormComponentWrap
子元素2
  • 通过connect()()创建的函数式组件,对外暴露实例和方法
import React, {forwardRef, useImperativeHandle} from 'react'
import { connect } from 'react-redux'

function Child2(props, ref){
	function parentCallChild2(){
		console.log('父组件调用子组件2的方法')
	}
	function c2Callc1(){
		console.log('兄弟元素通信 子组件2调用子组件1的方法')
		props.child2CallChild1()
	}
	// 将parentCallChild2方法暴露给父组件获取的实例
	useImperativeHandle(props.refInstance,()=>({parentCallChild2}))
	
	return <div onClick={this.c2Callc1}>Child2</div>
}

const Component = connect(matStateToProps,mapDispatchToProps)(Child2)
export default forwardRef((props, ref)=> <Component {...props} refInstance={ref} /> )

connect方法,连接react组件与redux中的store,将数据和UI连接起来,如果不写mapStateToProps参数,UI 组件就不会订阅Store, Store 的更新不会引起 UI 组件的更新;
matStateToProps是输入源,更新props;
mapDispatchToProps是输出源,更新action;

老版本框架获取实例

//父组件
this._childRef.current.getWrappedInstance()

//子组件
@connect(matStateToProps, mapDispatchToProps, mergeProps, { withRef: true })
export default connect(matStateToProps, mapDispatchToProps, mergeProps, { forwardRef: true })
export default connect(matStateToProps, mapDispatchToProps, mergeProps, { withRef: true })

获取类组件的实例

import React, {} from 'react'
import Child from '../child'
class Parent extends React.Component{
	constructor(){
		// this._childref = React.createRef();
	}
	callChildFunc(){
		//获取子组件实例 并调用方法
		this.refs._childref.getWrappedInstance().getName();
		this.refs._childref.wrappedInstance.getName();
		// this._childref.getName();
	}
	
	render(){
		return <Child ref={'_childref'} />
		// return <Child ref={this._childref} />
		// return <Child ref={ node => this._childref = node } />
	}
}

class Child extends React.Component{

	getName(){
		console.log('wan')
	}
	render(){
		return <Child ref={'_childref'} />
	}
}

withRouter的使用

高阶组件withRouter,是将一个组件包裹进Route里面,这个组件的this.props可以获取到react-router的三个对象history, location, match

对于不是通过路由跳转过来的组件,比如首页,如果想通过props获取路由信息,就需要用withRouter包裹这个组件

或者,比如通过this.props.history.push(’/1’)跳转页面,报错history是undefined,需要用withRouter包裹组件

import React,{Component} from 'react'
import {withRouter} from 'react-router-dom'

class App extends Component{
    //被withRouter包裹后才能获取history, match, location等路由信息对象
    console.log(this.props);
    
    constructor(props){
	  super(props);
	  // 通过history监听location变化 动态修改title
	  props.history.listen((location) => {
	    switch(location.pathname){
	      case '/1/1' :
	        document.title = '第一页';
	        break;
	      case '/1/2' :
	        document.title = '第二页';
	        break;
	      default : break;
	    }
	  })
	}
	
    render(){}
}
export default withRouter(App);

扩展-父元素调用子元素的方法

父-类组件 子-类组件

父-类组件 子-函数组件

父-函数组件 子-类组件

import Child from './Child'
const childRef = React.createRef()
function Parent(){
	//获取子元素实例的方法或变量
	//childRef.current.name
	//childRef.current.eat()
	return <Child ref={childRef} />
}

class Child extends React.PureComponent{
	constructor(props){
		super(props);
		this.eat = this.eat.bind(this);
		this.name = 'wanshaobo';
	}

	eat(){
		console.log('eat');
	}

	render(){
		return <div>1</div>
	}
}

父-函数组件 子-函数组件

import Child from './Child'
const childRef = React.createRef()
function Parent(){
	//获取子元素实例的方法或变量
	//childRef.current.name
	//childRef.current.eat()
	return <Child ref={childRef} />
}

import React, {forwardRef, useImperativeHandle} from 'react'
function Child(props, ref){
	const name = 'wanshaobo';
	const eat = ()=>{
		console.log('eat');
	}
	useImperativeHandle(ref, ()=>({name,eat}));
	return <div>1</div>
}
export default forwardRef(Child);
参考资料

感谢阅读,欢迎评论^-^

打赏我吧^-^

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

react函数式组件之兄弟组件中的方法互相调用 的相关文章

  • javascript函数知道它的名字吗

    我有一个名为 getItem 的函数 我想使用其中的代码读取该函数的名称 这可能吗 function getItem var functionName how do I read the function name alert functi
  • 整个页面都是玻璃板

    有没有一种简单的方法可以在整个 HTML 页面上拥有一个 玻璃窗格 而不管缩放 幻灯片事件 平台 浏览器 移动 桌面 我所说的 简单 是指纯 CSS 支持 而不是插件 后备 插件建议也可能有用 Thanks 如果您只是指所有内容之上的一层
  • 如果Functions是javascript中的对象,为什么function.constructor指向Function而不是Object?

    当像这样从窗口对象创建以下函数时 function userInfo 既然函数是对象 为什么 userInfo constructor 显示 Function 而不是 Object 当使用以下内容时 它甚至显示函数而不是对象 Functio
  • 方向改变后的javascript最大视口高度Android和iOS

    目标 查找设备的最大视口高度 包括设备的空间address bar这样我们就可以动态调整 min body 的大小并将内容向上推 问题 移动浏览器处理方向状态的方式不同 方向变化时更新 DOM 属性的方式也不同 使用 JavaScript
  • 流媒体性能 - Canvas 与

    我正在开发一个应用程序 需要通过 webSocket 连接以每秒至少 30 帧的速度持续传输图像 我遇到了一些性能问题 并希望尽我所能进行优化 我想知道使用不断更新的图像之间的性能差异是什么 就像这样 img src someDynamic
  • Node.js Google-云存储上传目的地规范

    我有一个 Node js 服务器并且正在使用谷歌云上传一些图像文件的包Firebase 存储 上传本身工作正常 但 google cloud API 似乎只能将文件上传到 Firebase Storage 根文件夹 有没有办法指定远程位置来
  • 为什么我的箭头函数有原型属性?

    正如文档中提到的https developer mozilla org en docs Web JavaScript Reference Functions Arrow functions https developer mozilla o
  • Chart.js - 如何将数组集合推入数据集

    我一直在尝试多种方法将数组集合推送到数据集中 任何人都可以帮助我根据下面的代码将数组推入堆积图表中 这是例子 Codepen 堆叠栏 https codepen io narendrajadhav pen abzpWam JavaScrip
  • 如何获得相对于特定父级的偏移量?

    我想获取元素相对于的偏移量特定的父母不是直接的 也不是文档 我在互联网上查找并找到了offset http api jquery com offset and position http api jquery com position jQ
  • 获取 pdf 第 1 页(共 2 页)的图像

    我正在使用 html2canvas 和 jsPDF 以及 Angular4 创建图像 我想将此图像放置在 2 页生成的 pdf 的第 1 页上 但似乎这条线 doc save test pdf 需要在函数内部htm2canvas 因为如果我
  • 将 javascript 放在 header 之外有多糟糕?

    这个问题几乎已经说明了一切 我开始添加一些功能到我的周末项目 http www my clock net 对于我和几个朋友来说 这是一个小应用程序 因为我们是交换生 所以它对我们来说有点有用 但事情是这样的 我在 php 中执行此操作并使用
  • 无法提取 Typescript 中的对象值

    我一直在尝试将 JavaScript Web 表单转换为 Typescript 但无法弄清楚如何处理以下内容 在 JavaScript 中有效 let fieldValues JSON parse cookieData let keys O
  • toJSON() 和 JSON.Stringify() 之间的区别

    如果您需要读取或克隆模型的所有数据属性 请使用其 toJSON 方法 此方法返回属性的副本作为 对象 尽管有其名称 但不是 JSON 字符串 当 JSON stringify 为 使用 toJSON 方法传递一个对象 它将返回的字符串化 t
  • 上传前如何检查图片的宽度和高度

    对于图片上传 我编写了以下 html 代码
  • 根据数据更改图例颜色高图表

    我可以根据数据动态设置列的颜色 但无法弄清楚如何更改图例中的颜色 请注意 jsfiddle 最新的条形图是绿色的 但图例是蓝色的 有没有办法改变列颜色也会改变图例颜色 这是我用于列颜色的代码 jsfiddle http jsfiddle n
  • 单击时突出显示文本(javascript jquery html)

    当您在所有浏览器中双击某个单词时 它们会自动突出显示单击下的单词 但是否有可能找到一种方法exact单击一下就会发生同样的事情吗 我想这涉及到的事情可能是 TextRange 的东西 对所有段落 或整个正文或 div 的 onclick 做
  • jQuery 单击附加元素不起作用

    我有一个数组 我正在从 Array 获取数据并在 jQuery Append to list 中使用它 但是当我单击列表项时 它只显示最后一个元素 var array 1 2 7 3 4 8 5 6 9 for var i 0 i lt a
  • .parents() 没有 jquery - 或 querySelectorAll 为父母[重复]

    这个问题在这里已经有答案了 可能的重复 使用 matchesSelector js 检查 event target parentElement https stackoverflow com questions 12977658 check
  • 自动更改 Twitter Bootstrap 选项卡

    我希望 Twitter Bootstrap 选项卡按时间顺序更改 我使用它们有点像旋转木马 我希望选项卡每 10 秒切换到下一个选项卡 这是一个例子 http library buffalo edu http library buffalo
  • 检测图像是否损坏或损坏

    我需要以编程方式检查用户在我的应用程序上选择作为壁纸的图像是否已损坏或损坏 基本上我为用户提供了选择自己的图像作为壁纸的选项 现在 当图像加载时 我只想检查它是否已损坏 如果您正在寻找 PHP 解决方案而不是 javascript 解决方案

随机推荐

  • vscode炫酷写代码插件Power Mode

    老规矩先看下效果 第一 扩展栏搜索 Power Mode 安装 安装完了别忘了重启 第二 文件 gt 首选项 gt 设置 gt 点击在setting json中编辑 powermode enabled true 是否开启 powermode
  • 爱线段树的好孩子[POI2014]KAR-Cards

    There are nn cards arranged on a table in a certain order Two integers are written on each card one per side the obverse
  • 解决cannot remove ''Operation not permitted

    删除某文件出现cannot remove XXX Operation not permitted lsattr 查看隐藏属性 root iZ2zehlrwqqmoadnuv8ts7Z home wwwroo wwwroot default
  • verilog中#是什么意思?#有什么作用?

    在使用verilog语言进行硬件描述时 你是否也经常用到 这个符号 那么你是否关心过这个符号到底是什么意思呢 它的作用是什么呢 1 可用作参数的传递 我们在进行verilog编程时经常会遇到如下一样的代码块 module study tes
  • -bash: zkServer.sh: command not found

    解决办法 zkServer sh start
  • qt 旋转子窗口 基于QGraphicsView 实现

    感谢 Qt 示例里边的 Box 示例 上图 不要被吓哭哦 X轴旋转 XY轴一起旋转 XYZ轴一起旋转 YZ轴一起旋转 Y轴旋转 XZ轴一起旋转 Z轴旋转 GIF的图有点略多 大家谅解谅解 上代码 http pan baidu com s 1
  • 学习注意力机制【1】

    目录 注意力机制介绍 自注意力机制三个步骤 1 计算注意力分数 Attention Scores 2 计算注意力权重 Attention Weights 3 得到加权和 Weighted Sum 自注意力机制Q K V 注意力机制介绍 At
  • 【JavaWeb】视频播放/下载

    如题 最近和同事联调接口时 收到反馈 ios低版本的视频播放不了 经网上查找其他大佬的解决方案修改 解决了该问题 话不多说 直接上代码 public static void downShowVideo HttpServletRequest
  • Python GUI案例之看图猜成语开发(第三篇)

    Python GUI案例之看图猜成语 第三篇 前言 看图猜成语小程序开发 第三篇 游戏闯关模式页面 Python GUI案例之看图猜成语开发 第一篇 Python GUI案例之看图猜成语开发 第二篇 Python GUI案例之看图猜成语开发
  • 中国“互联网+”大学生创新创业大赛“的实施方案及评审规则

    目录 前言 一 总体要求 一 指导思想 二 基本要求 三 总体目标 二 主要任务和措施 一 提升师资水平 1 增强教师创新创业教育的意识和能力 2 鼓励教师开设创新创业课程和指导创新创业实践 3 鼓励教师创新教学及考核方法 4 吸引校外师资
  • 开源跨平台跨硬件3D打印机

    1 HPGL 文档
  • DWD层 (用户行为日志)

    数仓搭建 DWD层 1 对用户行为数据解析 2 对业务数据采用维度模型重新建模 文章目录 日志解析思路 get json object函数使用 启动日志表 页面日志表 动作日志表 曝光日志表 错误日志表 DWD层用户行为数据加载脚本 日志解
  • Firefly-RK3399安装环境

    文章目录 Firefly RK3399 配置ubuntu环境以及安装Qt PCL OPENcv VTK 一 刷写ubuntu16 04系统 windows下 二 安装Qt Firefly RK3399 三 安装opencv pcl vtk
  • BUUCTF[knife]

    点击题目链接 发现是一句话木马 一句话木马 利用文件上传漏洞 往目标网站上上传木马 即可通过中国蚁剑或中国菜刀获取和控制整个网站主机目录 但很容易被网站防火墙waf拦截 想绕过waf需对木马进行变形 eval 函数 把括号内的字符串 须是合
  • ldconfig命令

    ldconfig命令 动态链接器的管理命令 依次搜索相关目录的动态链接库 lib so 创建动态链接装载程序 ld so或ld linux so 所需的链接和缓存文件 缓存文件 一般是 etc ld so cache 主要记录了动态链接库的
  • list元素

    列表元素 列表元素分为有序列表和无序列表 有序列表 ol order list 有序列表 li list item 列表元素 ol type 1 li 有序列表1 li li 有序列表2 li li 有序列表3 li ol 属性 type
  • [Leetcode] 414. 第三大的数

    题目描述 给定一个非空数组 返回此数组中第三大的数 如果不存在 则返回数组中最大的数 要求算法时间复杂度必须是O n 示例 1 输入 3 2 1 输出 1 解释 第三大的数是 1 示例 2 输入 1 2 输出 2 解释 第三大的数不存在 所
  • 发现一款好用的在线项目管理工具(有免费版)

    注 本文转载自网络 在线项目管理工具指的是不用安装服务器的云部署项目管理软件 这种部署方式的软件可随时开通 节约成本 但质量也参差不齐 考虑到多方面因素 我们公司最终决定用在线的项目管理工具 现在使用的工具是偶然参加展览会发现的 不得不说试
  • java实现远程桌面_?启迪云技术栈

    Openstack面板或命令行提供两种方式来对客户虚拟机进行远程桌面访问 VNC控制台和SPICE HTML5 VNC控制台 Openstack提供一个组件nova novncproxy 它允许用户通过浏览器或vnc客户端来访问虚拟机 通常
  • react函数式组件之兄弟组件中的方法互相调用

    最新更新时间 2022年01月15日14 40 31 猛戳 查看我的博客地图 总有你意想不到的惊喜 本文内容 一个父组件和两个子组件 三个组件都是函数式组件 子组件1需要调用子组件2的方法 同时子组件2需要调用子组件1的方法 技术方案分析