React 第十六章 Ref转发

2024-05-03 11:12

本文主要是介绍React 第十六章 Ref转发,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在 React 中,ref 是用来获取组件或者 DOM 元素的引用的一种机制。通过 ref ,你可以在函数组件中直接访问子组件的实例或者访问 DOM 元素。

然而,在某些情况下,你可能需要将 ref 传递给组件中的子组件,或者将 ref 传递到具有特定方法的 DOM 元素上。这就是 React ref 转发的作用。

React ref 转发允许某个组件接收一个 ref,并将其转发给其子组件中指定的 DOM 元素或组件。这样,你就可以在父组件中通过 ref 直接访问子组件的 DOM 元素或实例。

要实现 ref 转发,你需要在子组件中使用 React.forwardRef() 方法来创建一个新的组件,该方法接收一个回调函数作为参数。在这个回调函数中,你可以将传递给子组件的 ref 转发到子组件内部的某个 DOM 元素或子组件上。

下面是一个使用 React ref 转发的示例:

import React, { Component } from 'react'import withLogin from "./HOC/withLog";
import ChildCom1 from "./components/ChildCom1"
const NewChild = withLogin(ChildCom1);export default class App extends Component {constructor() {super();this.comRef = React.createRef();this.state = {show: true}}clickHandle = () => {// 查看当前的 Ref 所关联的组件console.log(this.comRef);}render() {return (<div><button onClick={() => this.setState({show: !this.state.show})}>show/hide</button><button onClick={this.clickHandle}>触发子组件方法</button>{this.state.show ? <NewChild ref={this.comRef} /> : null}</div>)}
}
// withLog.js
import { Component } from "react";
import { formatDate } from "../utils/tools";// 高阶组件是一个函数,接收一个组件作为参数
// 返回一个新的组件
function withLog(Com) {// 返回的新组件return class extends Component {constructor(props) {super(props);this.state = { n: 1 };}componentDidMount() {console.log(`日志:组件${Com.name}已经创建,创建时间${formatDate(Date.now(),"year-time")}`);}componentWillUnmount() {console.log(`日志:组件${Com.name}已经销毁,销毁时间${formatDate(Date.now(),"year-time")}`);}render() {return <Com {...this.props} />;}};
}export default withLog;
// ChildCom1.jsx
import React, { Component } from 'react'export default class ChildCom1 extends Component {test = () => {console.log("这是子组件的 test 方法");}render() {return (<div>ChildCom1</div>)}
}

在上面的三段代码中,我们使用了 withLog 这个高阶组件来包裹 ChildCom1 子组件,从而添加日志功能。在使用由高阶组件返回的增强组件时,我们传递了一个 Ref,我们的本意是想要这个 Ref 关联原本的子组件,从而可以触发子组件里面的方法。

但是我们会发现 Ref 关联的是高阶组件中返回增强组件,而非原来的子组件。

image-20221130135500947

要解决这个问题就会涉及到 Ref 的转发。说直白一点就是 Ref 的向下传递给子组件。

这里 React 官方为我们提供了一个 React.forwardRef API。我们需要修改的仅仅是高阶组件:

import React, { Component } from "react";
import { formatDate } from "../utils/tools";// 高阶组件是一个函数,接收一个组件作为参数
// 返回一个新的组件
function withLog(Com) {// 返回的新组件class WithLogCom extends Component {constructor(props) {super(props);this.state = { n: 1 };}componentDidMount() {console.log(`日志:组件${Com.name}已经创建,创建时间${formatDate(Date.now(),"year-time")}`);}componentWillUnmount() {console.log(`日志:组件${Com.name}已经销毁,销毁时间${formatDate(Date.now(),"year-time")}`);}render() {// 通过 this.props 能够拿到传递下来的 ref// 然后和子组件进行关联const {forwardedRef, ...rest} = this.props;return <Com ref={forwardedRef} {...rest} />;}}return React.forwardRef((props, ref) => {// 这里是关键,渲染函数会自动传入 ref,然后我们将 ref 继续往下传递return <WithLogCom {...props} forwardedRef={ref} />;});
}export default withLog;

在上面的代码中,React.forwardRef 接受一个渲染函数,该函数接收 propsref 参数并返回原本我们直接返回的增强组件。

接下来我们在增强组件的 render 方法中,通过 this.props 拿到 ref 继续传递给子组件。

那么 React.forwardRef 究竟做了啥呢?源码如下:

image-20221130135525552

可以看到,实际上 forwardRef 这个静态方法实际上也就是返回一个 elementType 的对象而已,该对象包含一个 render 方法,也就是我们在使用 React.forwardRef 时传入的渲染函数。

之所以要这么多此一举,是因为该渲染函数会自动传入 propsref,关键点就在这里,拿到 ref 后,后我们就可以将 ref 继续往下面传递给子组件。

总结来说,React ref 转发是一种将 ref 从一个组件传递到另一个组件的技术,通过它可以在父组件中直接访问子组件的 DOM 元素或实例。

这篇关于React 第十六章 Ref转发的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/956610

相关文章

HTML5中的Microdata与历史记录管理详解

《HTML5中的Microdata与历史记录管理详解》Microdata作为HTML5新增的一个特性,它允许开发者在HTML文档中添加更多的语义信息,以便于搜索引擎和浏览器更好地理解页面内容,本文将探... 目录html5中的Mijscrodata与历史记录管理背景简介html5中的Microdata使用M

html5的响应式布局的方法示例详解

《html5的响应式布局的方法示例详解》:本文主要介绍了HTML5中使用媒体查询和Flexbox进行响应式布局的方法,简要介绍了CSSGrid布局的基础知识和如何实现自动换行的网格布局,详细内容请阅读本文,希望能对你有所帮助... 一 使用媒体查询响应式布局        使用的参数@media这是常用的

HTML5表格语法格式详解

《HTML5表格语法格式详解》在HTML语法中,表格主要通过table、tr和td3个标签构成,本文通过实例代码讲解HTML5表格语法格式,感兴趣的朋友一起看看吧... 目录一、表格1.表格语法格式2.表格属性 3.例子二、不规则表格1.跨行2.跨列3.例子一、表格在html语法中,表格主要通过< tab

Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案

《Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案》:本文主要介绍Vue3组件中getCurrentInstance()获取App实例,但是返回nu... 目录vue3组件中getCurrentInstajavascriptnce()获取App实例,但是返回n

JS+HTML实现在线图片水印添加工具

《JS+HTML实现在线图片水印添加工具》在社交媒体和内容创作日益频繁的今天,如何保护原创内容、展示品牌身份成了一个不得不面对的问题,本文将实现一个完全基于HTML+CSS构建的现代化图片水印在线工具... 目录概述功能亮点使用方法技术解析延伸思考运行效果项目源码下载总结概述在社交媒体和内容创作日益频繁的

前端CSS Grid 布局示例详解

《前端CSSGrid布局示例详解》CSSGrid是一种二维布局系统,可以同时控制行和列,相比Flex(一维布局),更适合用在整体页面布局或复杂模块结构中,:本文主要介绍前端CSSGri... 目录css Grid 布局详解(通俗易懂版)一、概述二、基础概念三、创建 Grid 容器四、定义网格行和列五、设置行

前端下载文件时如何后端返回的文件流一些常见方法

《前端下载文件时如何后端返回的文件流一些常见方法》:本文主要介绍前端下载文件时如何后端返回的文件流一些常见方法,包括使用Blob和URL.createObjectURL创建下载链接,以及处理带有C... 目录1. 使用 Blob 和 URL.createObjectURL 创建下载链接例子:使用 Blob

Vuex Actions多参数传递的解决方案

《VuexActions多参数传递的解决方案》在Vuex中,actions的设计默认只支持单个参数传递,这有时会限制我们的使用场景,下面我将详细介绍几种处理多参数传递的解决方案,从基础到高级,... 目录一、对象封装法(推荐)二、参数解构法三、柯里化函数法四、Payload 工厂函数五、TypeScript

Vue3使用router,params传参为空问题

《Vue3使用router,params传参为空问题》:本文主要介绍Vue3使用router,params传参为空问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录vue3使用China编程router,params传参为空1.使用query方式传参2.使用 Histo

CSS Padding 和 Margin 区别全解析

《CSSPadding和Margin区别全解析》CSS中的padding和margin是两个非常基础且重要的属性,它们用于控制元素周围的空白区域,本文将详细介绍padding和... 目录css Padding 和 Margin 全解析1. Padding: 内边距2. Margin: 外边距3. Padd