IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> react函数式组件之兄弟组件中的方法互相调用 -> 正文阅读

[JavaScript知识库]react函数式组件之兄弟组件中的方法互相调用

最新更新时间: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);

参考资料

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

打赏我吧^-^

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-01-16 12:57:45  更:2022-01-16 12:58:24 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 12:25:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码