React高级指引之Refs and the DOM使用时机详解

 更新时间:2023年02月10日 13:59:03   作者:码农小菲  
在典型的React数据流中,props是父组件与子组件交互的唯一方式。要修改一个子组件,你需要使用新的props来重新渲染它。但是,在某些情况下,你需要在典型数据流之外强制修改子组件

Refs and the DOM

  • Refs 提供了一种方式,允许我们访问 DOM 节点或在 render 方法中创建的 React 元素
  • 在某些情况下,需要在典型数据流之外强制修改子组件。被修改的子组件可能是一个 React 组件的实例,也可能是一个 DOM 元素。

何时使用 Refs

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

勿过度使用 Refs

创建 Refs

  • React.createRef()创建
  • 通过 ref 属性附加到 React 元素
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }
  render() {
    return <div ref={this.myRef} />;
  }
}

访问 Refs

在 ref 的 current 属性中被访问

const node = this.myRef.current;

为 DOM 元素添加 ref

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);
    // 创建一个 ref 来存储 textInput 的 DOM 元素
    this.textInput = React.createRef();
    this.focusTextInput = this.focusTextInput.bind(this);
  }
  focusTextInput() {
    // 直接使用原生 API 使 text 输入框获得焦点
    // 注意:我们通过 "current" 来访问 DOM 节点
    this.textInput.current.focus();
  }
  render() {
    // 告诉 React 我们想把 <input> ref 关联到
    // 构造器里创建的 `textInput` 上
    return (
      <div>
        <input
          type="text"
          ref={this.textInput} />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focusTextInput}
        />
      </div>
    );
  }
}

为 class 组件添加 Ref

  class AutoFocusTextInput extends React.Component {
    constructor(props) {
      super(props);
      this.textInput = React.createRef();
    }
    componentDidMount() {
      this.textInput.current.focusTextInput();
    }
    render() {
      return (
        <CustomTextInput ref={this.textInput} />
      );
    }
  }

不能在函数组件上使用 ref 属性,如果要在函数组件中使用 ref,你可以使用 forwardRef(可与 useImperativeHandle 结合使用),或者可以将该组件转化为 class 组件

function CustomTextInput(props) {
   // 这里必须声明 textInput,这样 ref 才可以引用它
   const textInput = useRef(null);
   function handleClick() {
     textInput.current.focus();
   }
   return (
     <div>
       <input
         type="text"
         ref={textInput} />
       <input
         type="button"
         value="Focus the text input"
         onClick={handleClick}
       />
     </div>
   );
 }

将 DOM Refs 暴露给父组件

不建议暴露 DOM 节点

回调 Refs

  • 另一种设置 refs 的方式,称为“回调 refs”.
  • 能助你更精细地控制何时 refs 被设置和解除
  • 不同于传递 createRef() 创建的 ref 属性,你会传递一个函数。这个函数中接受 React 组件实例或 HTML DOM 元素作为参数,以使它们能在其他地方被存储和访问
    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>
       );
     }
   }
// 在上面的例子中,Parent 把它的 refs 回调函数当作 inputRef props 传递给了 CustomTextInput,而且 CustomTextInput 把相同的函数作为特殊的 ref 属性传递给了 <input>。结果是,在 Parent 中的 this.inputElement 会被设置为与 CustomTextInput 中的 input 元素相对应的 DOM 节点

如果 ref 回调函数是以内联函数的方式定义的,在更新过程中它会被执行两次,第一次传入参数 null,然后第二次会传入参数 DOM 元素。这是因为在每次渲染时会创建一个新的函数实例,所以 React 清空旧的 ref 并且设置新的。通过将 ref 的回调函数定义成 class 的绑定函数的方式可以避免上述问题,但是大多数情况下它是无关紧要的。

到此这篇关于React高级指引之Refs and the DOM使用时机详解的文章就介绍到这了,更多相关React Refs and the DOM内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:

相关文章

  • React18中请求数据的官方姿势适用其他框架

    React18中请求数据的官方姿势适用其他框架

    这篇文章主要为大家介绍了官方回答在React18中请求数据的正确姿势详解,同样也适用其他框架,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • useEffect中return函数的作用和执行时机解读

    useEffect中return函数的作用和执行时机解读

    这篇文章主要介绍了useEffect中return函数的作用和执行时机,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • 详解如何给React-Router添加路由页面切换时的过渡动画

    详解如何给React-Router添加路由页面切换时的过渡动画

    这篇文章主要介绍了详解如何给React-Router添加路由页面切换时的过渡动画,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-04-04
  • React split实现分割字符串的使用示例

    React split实现分割字符串的使用示例

    当我们需要将一个字符串按照指定的分隔符进行分割成数组时,我们可以在组件的生命周期方法中使用split方法来实现这个功能,本文就来介绍一下,感兴趣的可以了解下
    2023-10-10
  • 使用Ant Design Anchor组件的一个坑及解决

    使用Ant Design Anchor组件的一个坑及解决

    这篇文章主要介绍了使用Ant Design Anchor组件的一个坑及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • react脚手架构建运行时报错问题及解决

    react脚手架构建运行时报错问题及解决

    这篇文章主要介绍了react脚手架构建运行时报错问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • react Table准备Spin Empty ConfigProvider组件实现

    react Table准备Spin Empty ConfigProvider组件实现

    这篇文章主要为大家介绍了react Table准备Spin、Empty、ConfigProvider组件实现详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪<BR>
    2023-02-02
  • 详解如何用webpack4从零开始构建react开发环境

    详解如何用webpack4从零开始构建react开发环境

    这篇文章主要介绍了详解如何用webpack4从零开始构建react开发环境,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • 使用reactjs优化了进度条页面性能提高70%

    使用reactjs优化了进度条页面性能提高70%

    这篇文章主要介绍了使用reactjs优化了进度条后页面性能提高了70%的操作技巧,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-04-04
  • React错误边界Error Boundaries详解

    React错误边界Error Boundaries详解

    错误边界是一种React组件,这种组件可以捕获发生在其子组件树任何位置的JavaScript错误,并打印这些错误,同时展示降级UI,而并不会渲染那些发生崩溃的子组件树
    2022-12-12

最新评论