1.直接使用ref进行获取

  

import React, {Component} from 'react';

export default class Parent extends Component {
render() {
return(
<div>
<Child onRef={this.onRef} />
<button onClick={this.click} >click</button>
</div>
)
} onRef = (ref) => {
this.child = ref
} click = (e) => {
this.child.myName()
} } class Child extends Component {
componentDidMount(){
this.props.onRef(this)
} myName = () => alert('xiaohesong') render() {
return ('woqu')
}
}

  

2.假如是子组件是高阶组件的话,通过ref获取子组件实例方法。

  1. 子组件需要获取父组件的信息,这通过props就可以解决;
  2. 父组件需要知道子组件的信息,这可以通过ref解决。

我们这里讲的属于后者,但是又有些特殊,特殊就在于子组件是个高阶组件,比如使用@connect @withRouter包裹过的组件(其实大部分组件都会被这两个包裹),具体示例如下:

@withRouter
export default class childComponent extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (<div>this is childComponent</div>)
}
}
@withRouter
export default class parentComponent extends Component {
constructor(props) {
super(props);
this.state = {};
}
render () {
return <childComponent ref={(v) => { this.childCp = v; }}/>
}
}

  

上面的childComponent被withRouter包裹过一遍后,这时候你在parentComponent中通过ref获取到的是并不会是childComponent,而是withRouter组件。这就比较尴尬了,我们大多数情况肯定是需要获取自己写的组件实例的。有一点需要讲明白:就是通过ref获取到的不是childComponent,在原理上是对的,如果获取到是childComponent组件那才是有问题的,有悖伦理知道哇。

既然通过官方提供的ref无法获取到我们想要的ref,那我们就来仔细想下ref获取到的是啥?我们回归到javascript语言层面来看,那不就是组件中的this么。

@withRouter
export default class childComponent extends Component {
constructor(props) {
super(props);
this.state = {}; // 我们需要获取到的就是这个this而已
}
render() {
return (<div>this is childComponent</div>)
}
}

  

知道我们需要获取到的是啥了,那就好办了,我给childComponent传一个prop专门来get这个this不就好了,比如使用getInstance

@withRouter
export default class childComponent extends Component {
constructor(props) {
super(props);
this.state = {};
const { getInstance } = props;
if (typeof getInstance === 'function') {
getInstance(this); // 在这里把this暴露给`parentComponent`
}
}
render() {
return (<div>this is childComponent</div>)
}
}
@withRouter
export default class parentComponent extends Component {
constructor(props) {
super(props);
this.state = {};
}
render () {
return (
<childComponent
ref={(withRouter) => { this.childCpWrapper = withRouter; }} // 这里获取的是`withRouter`组件,一般没啥用,这里写出来只是为了对比
getInstance={(childCp) => { this.childCp = childCp; }} // 这里通过`getInstance`传一个回调函数接收`childComponent`实例即可
/>
);
}
}

  

perfect ! 问题解决了,这样我不管你怎么用啥高阶组件、用多少个高阶组件包裹我们childComponent,我们都可以通过一个getInstance,穿越千山万水直接获取childComponent实例。

当然完美也是相对的,比如上面的方案中,我们得在每一个childComponent的构造函数中写那段暴露this的代码,麻烦、费劲。这时候我们可以写一个HOC专门来做这件事情,比如withRef:

// 只做一件事,把`WrappedComponent`回传个`getInstance`(如果有的话)
export default (WrappedComponent) => {
return class withRef extends Component {
static displayName = `withRef(${WrappedComponent.displayName || WrappedComponent.name || 'Component'})`;
render() {
// 这里重新定义一个props的原因是:
// 你直接去修改this.props.ref在react开发模式下会报错,不允许你去修改
const props = {
...this.props,
};
// 在这里把getInstance赋值给ref,
// 传给`WrappedComponent`,这样就getInstance能获取到`WrappedComponent`实例
// 感谢评论区的[yangshenghaha]同学的完善
props.ref = (el)=>{
this.props.getInstance && this.props.getInstance(el);this.props.ref && this.props.ref(el);
}
return (
<WrappedComponent {...props} />
);
}
};
};

  

然后我们可以这样使用withRef

@withRouter
@withRef // 这样使用是不是方便多了,注意:这句必须写在最接近`childComponent`的地方
export default class childComponent extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (<div>this is childComponent</div>)
}
}
@withRouter
export default class parentComponent extends Component {
constructor(props) {
super(props);
this.state = {};
}
render () {
return (
<childComponent
// 这里获取的是`withRouter`组件,一般没啥用,这里写出来只是为了对比
ref={(withRouter) => { this.childCpWrapper = withRouter; }}
// 这里通过`getInstance`传一个回调函数接收`childComponent`实例即可
getInstance={(childCp) => { this.childCp = childCp; }}
/>
);
}
}

  

react中父组件调用子组件的方法的更多相关文章

  1. react 父组件调用子组件方法

    import React from 'react'import '../page1/header.css'import { Table } from 'antd'import Child from ' ...

  2. React 父组件调用子组件的方法

    父组件调用子组件的方法 React v16.3.0 及以后版本使用 import React, {Component} from 'react'; export default class Paren ...

  3. vue+element ui项目总结点(四)零散细节概念巩固如vue父组件调用子组件的方法、拷贝数据、数组置空问题 等

    vue config下面的index.js配置host: '0.0.0.0',共享ip (假设你的电脑启动了这个服务我电脑一样可以启动)-------------------------------- ...

  4. 父组件调用子组件 viewChild

    父组件调用子组件 1.在子组件的ts中声明一个变量 public  lineout:any="你好,我是被父组件调用的子组件";  2.在父组件的html中写入 (引入子组件) & ...

  5. vue:父子组件间通信,父组件调用子组件方法进行校验子组件的表单

    参考: ElementUI多个子组件表单的校验管理:https://www.jianshu.com/p/541d8b18cf95 Vue 子组件调用父组件方法总结:https://juejin.im/ ...

  6. vue中子组件调用父组件里面的数据和方法 父组件调用子组件的数据和方法

    1.子组件直接调用父组件的数据和方法 在父组件father,vue <template> <div> <!-- 父组件里面的数据 --> <p>父组件里 ...

  7. vue 父组件调用子组件内置方法

    背景介绍:外派到泰康做项目.这个项目中有个选择组织的功能,是一个树桩结构的懒加载,于是我就element-ui的tree组件封装了一个公共的组件. 但是后来发现他们的公司组织结构不是都请求的同一个接口 ...

  8. Vue 父组件调用子组件的方法

    qwq  前两天看了下vue,父子组件方法的调用,怕忘记,所以做个小记录. 一.父组件调用子组件的方法 1.父组件 <template> <div id="rightmen ...

  9. vue父组件调用子组件方法、父组件向子组件传值、子组件向父组件传值

      一.父组件调用子组件方法 父组件代码  parent.vue <template> <div> <button @click="parentFun" ...

  10. Vue3 父组件调用子组件的方法

    Vue3 父组件调用子组件的方法 // 父组件 <template> <div> 父页面 <son-com ref="sonRef"/> < ...

随机推荐

  1. IBM WebSphere MQ for net 报错 MQRC_NOT_AUTHORIZED

    最近进入新公司要维护以前的90年代的老系统 用NET对IBMMQ做测试 NET 4.0 +7.5 MQ 版本 待我写好NET调用的代码后出现错误MQRC_NOT_AUTHORIZED 折腾大半天往上找 ...

  2. zw版【转发·台湾nvp系列Delphi例程】HALCON TestSubsetRegio

    zw版[转发·台湾nvp系列Delphi例程]HALCON TestSubsetRegio procedure TForm1.Button1Click(Sender: TObject);var rg0 ...

  3. ZW网络团队及资源简介

    ZW网络团队及资源简介 ZW网络推广团队,是国内首个教父级网络营销团队,自1997年以来,先后参与操盘多个重大互联网项目,服务过超过150家国际500强客户,是微软公司首家官方认证的网络公关服务商,新 ...

  4. 2017-2018-2 20165207实验二《Java面向对象程序设计》实验报告

    2017-2018-2 20165207实验二<Java面向对象程序设计>实验报告 课程:Java程序设计 班级:1652 姓名:李天林 学号:20165207 实验日期:2018年4月1 ...

  5. Jsuop Whitelist

    Jsuop使用示例代码 使用jsoup HTML Cleaner 方法进行清除,但需要指定一个可配置的 Whitelist.http://jsoup.org/apidocs/org/jsoup/saf ...

  6. WdatePicker显示乱码

    1.修改zh-cn.js内容: var $lang={ errAlertMsg: "不合法的日期格式或者日期超出限定范围,需要撤销吗?", aWeekStr: ["周&q ...

  7. deepin中crossover或playonlinux装完office后word无法输入中文的问题

    原因:office安装是自带了一个微软输入法 解决:装offce时进行自定义安装,在office共享功能里,把输入法去掉. 参考: https://jingyan.baidu.com/article/ ...

  8. SQL学习笔记五之MySQL索引原理与慢查询优化

    阅读目录 一 介绍 二 索引的原理 三 索引的数据结构 四 聚集索引与辅助索引 五 MySQL索引管理 六 测试索引 七 正确使用索引 八 联合索引与覆盖索引 九 查询优化神器-explain 十 慢 ...

  9. linux各版本基线检查脚本(centos6、centos7、ubuntu系列)

    以下是centos7基线检查脚本: #!/bin/bash #version v1. by pensar #操作系统linux 配置规范--centos7 cat <<EOF ****** ...

  10. 20155201 2016-2017-2 《Java程序设计》第四周学习总结

    20155201 2016-2017-2 <Java程序设计>第四周学习总结 教材学习内容总结 - 第六章要点: 继承:面向对象中,子类继承父类,避免重复的行为定义.继承基本上就是避免多个 ...