资讯专栏INFORMATION COLUMN

React父组件调用子组件中的方法实例详解

3403771864 / 24人阅读

  本文主要讲述ref 的应用仅为父组件调用子组件场景下的应用方式1

  Class组件

  1. 自定义事件

   Parent.js

  import React, { Component } from 'react';
  import Child from './Child';
  class Parent extends Component {
  componentDidMount () {
  console.log(this.childRef)
  }
  handleChildEvent = (ref) => {
  // 将子组件的实例存到 this.childRef 中, 这样整个父组件就能拿到
  this.childRef = ref
  }
  //按钮事件处理
  handleClick = () => {
  // 通过子组件的实例调用组组件中的方法
  this.childRef.sendMessage()
  }
  render () {
  return (
  <>
  <Child
  onChildEvent={this.handleChildEvent}
  />
  <button onClick={this.handleClick}>Trigger Child Event</button>
  </>
  );
  }
  }
  export default Parent;

  Child.js

  import React, { Component } from 'react';
  class Child extends Component {
  //子组件完成挂载时, 将子组件的方法 this 作为参数传到父组件的函数中
  componentDidMount () {
  // 在子组件中调用父组件的方法,并把当前的实例传进去
  this.props.onChildEvent(this)
  }
  // 子组件的方法, 在父组件中触发
  sendMessage = () => {
  console.log('sending message')
  }
  render () {
  return ( <div>Child</div> );
  }
  }
  export default Child;
  2. 使用 React.createRef()

  ParentCmp.js

  import React, { Component } from 'react';
  import ChildCmp from './ChildCmp';
  export default class ParentCmp extends Component {
  constructor(props) {
  super(props)
  // 创建Ref
  this.childRef = React.createRef()
  }
  // 按钮事件
  handleClick = () => {
  // 直接通过 this.childRef.current 拿到子组件实例
  this.childRef.current.sendMessage()
  }
  render () {
  return (
  <>
  <ChildCmp ref={this.childRef} />
  <button onClick={this.handleClick}>Trigger Child Event</button>
  </>
  );
  }
  }

  而子组件就是一个普通的组件

  ChildCmp.js

  import React, { Component } from 'react';
  export default class ChildCmp extends Component {
  sendMessage = () => {
  console.log('sending message')
  }
  render () {
  return 'Child';
  }
  }

  3. 使用回调Refs

  回调 Refs 是另一种设置 Ref 的方式,可以控制 refs 被设置和解除的时间。

  此时,需要传递一个函数,不同于传递 createRef() 创建的 ref 属性。

   current也不是访问 Ref 必需。

  ParentCmp.js

  import React, { Component } from 'react';
  import ChildCmp from './ChildCmp';
  export default class ParentCmp extends Component {
  constructor(props) {
  super(props)
  // 创建 Ref,不通过 React.createRef()
  this.childRef = null
  }
  // 设置 Ref
  setChildRef = (ref) => {
  this.childRef = ref
  }
  // 按钮事件
  handleClick = () => {
  // 直接通过 this.childRef 拿到子组件实例
  this.childRef.sendMessage(`Trigger Child Event from Parent`)
  }
  render () {
  return (
  <>
  <ChildCmp ref={this.setChildRef} />
  <button onClick={this.handleClick}>Trigger Child Event</button>
  </>
  );
  }
  }

  而子组件还是一个普通的组件

  ChildCmp.js

  import { Component } from 'react';
  export default class ChildCmp extends Component {
  sendMessage = (message) => {
  console.log('sending message:', message)
  }
  render () {
  return 'Child';
  }
  }

  【注】对比自定义事件方式,回调 Refs 更像是精简的自定义事件方式:

  在自定义事件名称变成了 ref之后,子组件内无需手动绑定。

  Function组件

  在普通默认情况下,无法在函数组件上使用 ref 属性,主要是没有实例。上述两种方式都行不通。

  解决办法就是使用 forwardRef 和 useImperativeHandle。

  不过在函数的内部是可以使用 useRef 钩子来获取组件内的 DOM 元素。

  Parent.js

  import React, { useRef } from 'react';
  import Child from './Child';
  const Parent = () => {
  // 通过 Hooks 创建 Ref
  const childRef = useRef(null)
  const handleClick = () => {
  childRef.current.sendMessage()
  }
  return (
  <>
  <Child
  ref={childRef}
  />
  <button onClick={handleClick}>Trigger Child Event</button>
  </>
  );
  }
  export default Parent;

  Child.js

  import React, { forwardRef, useImperativeHandle } from 'react';
  const Child = forwardRef((props, ref) => {
  //将子组件的方法 暴露给父组件
  useImperativeHandle(ref, () => ({
  sendMessage
  }))
  const sendMessage = () => {
  console.log('sending message')
  }
  return ( <div>Child</div> );
  })
  export default Child;

  注:

  上面的例子中只是简单地演示了父子组件之间的方法调用,当然实际情况中子组件中可以也会有自己的 ref 指向自己内部的 DOM 元素,不过这些原理都是一样的。

  补充:子组件调用父组件方法

  子组件中调用父组件的setId方法

  父组件

  <NavBarX
  item={item}
  current={current}
  getBatchDetails={(id) => this.getBatchDetails(0, id)}
  setId={(id, callback) => this.setState({ id }, callback)}
  onRef={this.onNavBarXRef}
  />

  子组件

  this.props.setId(prePageId, () => {
  getBatchDetails(prePageId)
  })

       上述就是全部内容,后续请大家多多关注!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/127716.html

相关文章

  • 5、React组件事件详解

    React组件事件响应 React在构建虚拟DOM的同时,还构建了自己的事件系统;且所有事件对象和W3C规范保持一致。 React的事件系统和浏览器事件系统相比,主要增加了两个特性:事件代理、和事件自动绑定。 1、事件代理 区别于...

    Ververica 评论0 收藏0
  • 简述 React 组件生命周期

    ... 1 次,而且一定会调用 1 次: getDefaultProps() 这个方法组件实例创建前,也就是构造函数执行前执行,获取组件传来的参数,你可以在这里编辑参数并返回新的参数作为 props getInitalState() 组件创建的一开始会调用这个方法初...

    qpal 评论0 收藏0
  • React入门看这篇就够了

    ...的库 React 官网 React 中文文档 特点 1 使用 JSX语法 创建组件,实现组件化开发,为函数式的 UI 编程方式打开了大门 2 性能高的让人称赞:通过 diff算法 和 虚拟DOM 实现视图的高效更新 3 HTML仅仅是个开始 > JSX --TO--> EveryThing - J...

    luckyw 评论0 收藏0
  • React的Refs方法获取DOM实例 和 访问组件方法及属性

    ...常特殊的属性 Ref ,你可以用来绑定到 render() 输出的任何组件上。 ref : 绑定属性 refs : 调用的时候使用 调用组件方法 这是一个很神奇的方法refs,它可以调用组件方法以及属性。下面用一个例来实现调用组件方法。 ...

    geekzhou 评论0 收藏0
  • React

    ... 提供基础API:创建元素,渲染元素。 React的独特之处: 组件的组合模式,单向数据流的设计(Date Flow),高效的性能(Virtual DOM),分离的设计 React的核心思想:封装组件,各个组件维护自己的状态和 UI, 当状态变更,自动重新渲染...

    hlcc 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<