前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【React】:Refs

【React】:Refs

作者头像
WEBJ2EE
发布于 2020-04-07 02:44:16
发布于 2020-04-07 02:44:16
1.1K00
代码可运行
举报
文章被收录于专栏:WebJ2EEWebJ2EE
运行总次数:0
代码可运行
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
目录
1. Refs
   1.1. Refs 适合干什么
   1.2. 创建、添加、访问 Refs
   1.3. Callback Refs
2. Forwarding Refs
3. Hooks
   3.1. useRef
   3.2. useImperativeHandle

1. Refs

Refs 提供了一种方式,允许我们访问 DOM 节点或在 render 方法中创建的 React 元素

勿过度使用 Refs

1.1. Refs 适合干什么

  • 管理焦点,文本选择或媒体播放。
  • 触发强制动画。
  • 与 ActiveX 控件交互。
  • 集成第三方 DOM 库。

1.2. 创建、添加、访问 Refs

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 创建 Refs
this.myRef = React.createRef();
// 添加 Refs
<SomeClassComponent ref={this.myRef}/>
<someHtmlElement ref={this.myRef}/>
// 引用 Refs
const node = this.myRef.current;
  • ref 用于 HTML 元素时,ref.current 指向 DOM 元素。
  • ref 用于自定义 class 组件时,ref.current 指向组件的挂载实例。
  • ref 不能用在 function 组件上(因为 fucntion 组件没有实例)。

示例1:ref->DOM

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React from "react"

class HelloWorld extends React.Component{
    constructor(props) {
        super(props);
        this.myRef = React.createRef<HTMLInputElement>();
    }
    
    componentDidMount(): void {
        this.myRef.current.value = "HelloWorld!";
        this.myRef.current.focus();
    }

    render() {
        return <input ref={this.myRef} type={"text"} />;
    }
}

export default function App(){
    return (
        <HelloWorld/>
    );
}

示例2:ref->class 组件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React from "react"

class HelloWorld extends React.Component{
    constructor(props) {
        super(props);
        this.myRef = React.createRef();
    }

    changeBgColor(bgcolor): void {
        this.myRef.current.style.backgroundColor = bgcolor;
    }

    render() {
        return <input ref={this.myRef} type={"text"} />;
    }
}

export default class App extends React.Component{
    constructor(props) {
        super(props);
        this.myRef = React.createRef();
    }

    componentDidMount(): void {
        this.myRef.current.changeBgColor("purple");
    }

    render() {
        return <HelloWorld ref={this.myRef}/>;
    };
}

1.3. Callback Refs

除了使用 createRef() 创建的 ref 属性,React 也支持通过 callback 设置 refs。

示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React from "react"

class CustomTextInput extends React.Component {
    constructor(props) {
        super(props);

        this.textInput = null;

        this.setTextInputRef = element => {
            this.textInput = element;
        };

        this.focusTextInput = () => {
            // 使用原生 DOM API 使 text 输入框获得焦点
            if (this.textInput) this.textInput.focus();
        };
    }

    componentDidMount() {
        // 组件挂载后,让文本框自动获得焦点
        this.focusTextInput();
    }

    render() {
        // 使用 `ref` 的回调函数将 text 输入框 DOM 节点的引用存储到 React
        // 实例上(比如 this.textInput)
        return (
            <div>
                <input
                    type="text"
                    ref={this.setTextInputRef}
                />
                <input
                    type="button"
                    value="Focus the text input"
                    onClick={this.focusTextInput}
                />
            </div>
        );
    }
}

export default function App(){
    return <CustomTextInput/>
}

示例2:Parent direct visit child's DOM

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React from "react"

function CustomTextInput(props) {
    return (
        <div>
            {/* eslint-disable-next-line react/prop-types */}
            <input ref={props.inputRef}/>
        </div>
    );
}

class Parent extends React.Component {
    constructor(props) {
        super(props);
        this.inputElement = null;
    }

    focusTextInput = () => {
        if (this.inputElement) {
            this.inputElement.focus();
        }
    }

    saveInputRef = (el) => {
        this.inputElement = el;
    }

    render() {
        return (
            <div>
                <CustomTextInput inputRef={this.saveInputRef}/>
                <input
                    type="button"
                    value="Focus the text input"
                    onClick={this.focusTextInput}
                />
            </div>
        );
    }
}

export default function App() {
    return <Parent/>
}

Parent 把它的 refs 回调函数当作 inputRef props 传递给了 CustomTextInput,而且 CustomTextInput 把相同的函数作为特殊的 ref 属性传递给了 <input>。结果是,在 Parent 中的 this.inputElement 会被设置为与 CustomTextInput 中的 input 元素相对应的 DOM 节点。

2. Forwarding Refs

Ref 转发允许某些组件接收 ref,并将其向下传递(或者说“转发”)给子组件。

勿过度使用 Refs

API

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
React.forwardRef

示例1:React.forwardRef

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React from "react"

const FancyButton = React.forwardRef((props, ref) => (
    <button ref={ref} className="FancyButton">
        {props.children}
    </button>
));

export default class App extends React.Component{
    constructor(props) {
        super(props);
        this.ref = React.createRef();
    }

    componentDidMount(): void {
        console.log(this.ref.current);
    }

    render(){
        return <FancyButton ref={this.ref}>Click me!</FancyButton>;
    }
}
  1. 我们通过调用 React.createRef 创建了一个 React ref 并将其赋值给 ref 变量。
  2. 我们通过指定 ref 为 JSX 属性,将其向下传递给 <FancyButton ref={ref}>。
  3. React 传递 ref 给 forwardRef 内函数 (props, ref) => ...,作为其第二个参数。
  4. 我们向下转发该 ref 参数到 <button ref={ref}>,将其指定为 JSX 属性。
  5. 当 ref 挂载完成,ref.current 将指向 <button> DOM 节点。

示例2:HOC + Forwarding Refs

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function logProps(Component) {
  class LogProps extends React.Component {
    componentDidUpdate(prevProps) {
      console.log('old props:', prevProps);
      console.log('new props:', this.props);
    }

    render() {
      const {forwardedRef, ...rest} = this.props;

      // 将自定义的 prop 属性 “forwardedRef” 定义为 ref
      return <Component ref={forwardedRef} {...rest} />;
    }
  }

  // 注意 React.forwardRef 回调的第二个参数 “ref”。
  // 我们可以将其作为常规 prop 属性传递给 LogProps,例如 “forwardedRef”
  // 然后它就可以被挂载到被 LogProps 包裹的子组件上。
  return React.forwardRef((props, ref) => {
    return <LogProps {...props} forwardedRef={ref} />;
  });
}

示例3:HOC + Forwarding Refs + React Dev Tools

React.forwardRef 接受一个渲染函数。React DevTools 使用该函数来决定为 ref 转发组件显示的内容。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React from "react"

class FancyButton extends React.Component {
    focus() {
        // ...
    }

    render(){
        return "FancyButton";
    }
}

// HOC
function logProps(Component) {
    class LogProps extends React.Component {
        render() {
            const {forwardedRef, ...rest} = this.props;

            // 将自定义的 prop 属性 “forwardedRef” 定义为 ref
            return <Component ref={forwardedRef} {...rest} />;
        }
    }

    // 如果命名了渲染函数,DevTools 也将包含其名称(例如 “ForwardRef(myFunction)”)
    function myForwardRef(props, ref){
        return <LogProps {...props} forwardedRef={ref} />;
    }

    return React.forwardRef(myForwardRef);
}

// HOC(FancyButton)
const WrappedFancyButton = logProps(FancyButton);

export default class App extends React.Component{
    constructor(props) {
        super(props);
        this.ref = React.createRef();
    }

    componentDidMount(): void {
        console.log(this.ref.current);
    }

    render(){
        return <WrappedFancyButton ref={this.ref}/>;
    }
}

3. Hooks

勿过度使用 Refs

3.1. useRef

useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内保持不变。

示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React, {useRef} from "react"

function HelloWorld(){
    const myRef = useRef(null);

    const onButtonClick = () => {
        myRef.current.value = "HelloWorld!";
        myRef.current.focus();
    }

    return (<>
        <input ref={myRef} type="text" />
        <button onClick={onButtonClick}>Click</button>
    </>);
}

export default function App(){
    return (
        <HelloWorld/>
    );
}

3.2. useImperativeHandle

useImperativeHandle 可以让你在使用 ref 时自定义暴露给父组件的实例值。useImperativeHandle 应当与 React.forwardRef 一起使用:

示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React, {useRef, useEffect, useImperativeHandle} from "react"

function HelloWorld(props, ref){
    const myRef = useRef(null);

    useImperativeHandle(ref, ()=>({
        changeBgColor(bgcolor) {
            myRef.current.style.backgroundColor = bgcolor;
        }
    }));

    return <input ref={myRef} type={"text"} />;
}

HelloWorld = React.forwardRef(HelloWorld);

export default function App(){

    const myRef = useRef(null);

    useEffect(()=>{
        myRef.current.changeBgColor("purple");
    });

    return <HelloWorld ref={myRef}/>;
}

参考:

https://react.docschina.org/docs/hooks-reference.html#useref

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 WebJ2EE 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
React的ref是怎样调用其他元素?
ref 可以理解为指向React 元素的变量,方便其他组件访问这个React元素。
Learn-anything.cn
2021/11/28
1K0
[OHIF-Viewers]医疗数字阅片-医学影像-REACT-React.createRef()-Refs and the DOM关于回调 refs 的说明
Refs 提供了一种方式,允许我们访问 DOM 节点或在 render 方法中创建的 React 元素。
landv
2020/07/09
1.8K0
【React】243- 在 React 组件中使用 Refs 指南
本文通过四种方式来告诉你如何使用,虽然有一种被放弃了。今日早读文章由老虎集团@joking_zhang翻译授权分享。
pingan8787
2019/07/25
4.1K0
【React】243- 在 React 组件中使用 Refs 指南
小结React(三):state、props、Refs
在React中state、props、Refs都是最基础的概念,本文将同时梳理下这三个知识点,主要内容包括:
前端林子
2019/05/02
7.5K1
小结React(三):state、props、Refs
React 16.3新API
之前也有context,相当于自动向下传递的props,子树中的任意组件都可以从context中按需取值(配合contextTypes声明)
ayqy贾杰
2019/06/12
1.1K0
React 16.3新API
React Forwarding高阶组件传递Refs
通常情况下,我们想获取一个组建或则一个HTML元素的实例通过 Ref特性 就可以实现,但是某些时候我们需要在子父级组建中传递使用实例,Forwarding Refs提供了一种技术手段来满足这个要求,特别是开发一些重复使用的组建库时。比如下面的例子:
随风溜达的向日葵
2018/08/15
1.3K0
【React】你想知道的关于 Refs 的知识都在这了
Refs 提供了一种方式,允许我们访问 DOM 节点或在 render 方法中创建的 React 元素。
Nealyang
2019/11/08
3.1K0
浅谈 React Refs
在React组件中,props是父组件与子组件的唯一通信方式,但是在某些情况下我们需要在props之外强制修改子组件或DOM元素,这种情况下React提供了Refs解决
IMWeb前端团队
2019/12/03
1K0
浅谈 React Refs
React 中refs的使用方法和步骤
在 React 中,ref 是一种用于访问组件或 DOM 元素的引用的特殊属性。在组件中存储对 DOM 节点或组件实例的引用,直接访问和操作
王小婷
2023/10/10
4510
React ref 的前世今生
众所周知,React 通过声明式的渲染机制把复杂的 DOM 操作抽象成为简单的 state 与 props 操作,一时圈粉无数,一夜间将前端工程师从面条式的 DOM 操作中拯救出来。尽管我们一再强调在 React 开发中尽量避免 DOM 操作,但在一些场景中仍然无法避免。当然 React 并没有把路堵死,它提供了 ref 用于访问在 render 方法中创建的 DOM 元素或者是 React 组件实例。
Nealyang
2019/09/29
8980
超性感的React Hooks(十)useRef
在函数式组件中,useRef 是一个返回可变引用对象的函数。该对象.current属性的初始值为useRef传入的参数initialVale。
用户6901603
2020/07/27
3.4K0
超性感的React Hooks(十)useRef
React的三大属性之refs的一些简单理解
React 将在组件挂载时,会调用 ref 回调函数并传入 DOM 元素,当卸载时调用它并传入 null。在 componentDidMount 或 componentDidUpdate 触发前,React 会保证 refs 一定是最新的。
henu_Newxc03
2021/12/26
8730
React 16 新特性全解(上)
本次系列分上下两篇文章,上主要介绍从v16.0~ 16.4的新特性,下主要介绍16.5~16.8。下面就开始吧~
前端迷
2019/07/12
1.6K0
React 16 新特性全解(上)
2021前端react面试题汇总
(2)区别 Redux更多的是遵循Flux模式的一种实现,是一个 JavaScript库,它关注点主要是以下几方面∶
zz1998
2021/09/24
2.4K0
在React 中,如何创建refs?
在类组件中,可以使用 React.createRef() 方法来创建 ref 对象。通常,在组件的构造函数中将 ref 赋值给类的实例属性。
王小婷
2023/10/10
8190
React 进阶 - Ref
ref 对象就是用 createRef 或者 useRef 创建出来的对象,一个标准的 ref 对象应该是如下的样子:
Cellinlab
2023/05/17
1.8K0
React 进阶 - Ref
常见react面试题(持续更新中)
每个React组件强制要求必须有一个 render()。它返回一个 React 元素,是原生 DOM 组件的表示。如果需要渲染多个 HTML 元素,则必须将它们组合在一个封闭标记内,例如 <form>、<group>、<div> 等。此函数必须保持纯净,即必须每次调用时都返回相同的结果。
beifeng1996
2022/12/16
2.7K0
这个 hook api,是 useState 的双生兄弟
使用函数创建组件,有一个非常特殊的地方。那就是当组件重新刷新时,组件函数会重新执行。于是在这种情况下,如何在函数内部持久化保存一个数据或者状态就变成了一个需要探讨的问题。
用户6901603
2022/05/24
1.2K0
react入门(三):state、ref & dom简解
作用:组件内部的状态重新更新时,可以控制组件内部重新渲染(不需要重新调取组件也可以重新渲染)
柴小智
2020/02/12
8990
React源码解析之React.createRef()/forwardRef()
一、React.createRef() GitHub: https://github.com/AttackXiaoJinJin/reactExplain/blob/master/react16.8.6/packages/react/src/ReactCreateRef.js
进击的小进进
2019/09/05
1.6K0
React源码解析之React.createRef()/forwardRef()
相关推荐
React的ref是怎样调用其他元素?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验