zoukankan      html  css  js  c++  java
  • React Hooks之useRef、createRef、forwardRef

    一 Ref(reference)引用:用于直接使用dom元素的某个方法,或者直接使用自定义组件中的某个方法。处理对象:管理焦点,文本选择,媒体播放(媒体回放);触发动画;集成第三方的DOM库。

    1. 作用于内置的html组件,得到的是真实的dom
    2. ref作用于类组件,得到的是类的实例
    3. ref不能作用于函数组件
    4. Ref不推荐字符串方式,一般是函数或者对象方式引用。
    import React, { Component, createRef } from 'react';
    
    export default class Test extends Component {
      constructor(props){
        super(props)
        this.createRefTxt = createRef()
      }
      handleFnClick = () => {
        console.log(this.fnTxt);
        this.fnTxt.focus();
      };
    
      handleObjectClick = () => {
        console.log(this.createRefTxt);
        this.createRefTxt.current.focus();
      };
    
      render () {
        return (
          <>
            <div className="func-way">
              <input
                ref={(el) => { this.fnTxt = el; }}
                type='text'
              />
              <button onClick={this.handleFnClick}>函数方式</button>
            </div>
            <div className="object-way">
              <input
                ref={this.createRefTxt}
                type='text'
              />
              <button onClick={this.handleObjectClick}>对象方式</button>
            </div>
          </>
    
        );
      }
    }
    View Code

    二 useRef、createRef、forwardRef区别:

    1 useRef:

    一般用于函数组件

    useRef 不仅仅是用来管理 DOM ref 的,它还相当于 this , 可以存放任何变量。

    当 useRef 的内容发生变化时,它不会通知您。更改.current属性不会导致组件重新渲染。因为他一直是一个引用 。

    2 createRef:

    一般用于类组件,React.createRef 创建一个能够通过 ref 属性附加到 React 元素的 ref。

    如果用于函数组件中,当App这个函数组件被重新渲染时,App函数将会执行,并且重新创建、初始化所有的变量和表达式。因此,createRef每次都会被执行,所以对应的值总是为null。

    createRef 每次渲染都会返回一个新的引用,而 useRef 每次都会返回相同的引用。

    3 forwardRef:

    Ref 转发是一个可选特性,其允许某些组件接收 ref,并将其向下传递(换句话说,“转发”它)给子组件。

    import React, { Component } from 'react'
    
    function A(props, ref){
      console.log(props, ref)
      return <h1 ref={ref}>A组件</h1>
    }
    
    // 传递函数组件,得到一个新的组件,不能传递类组件,并且函数组件必须使用第二个
    const NewA = React.forwardRef(A)
    export default class Test extends Component {
      ARef = React.createRef()
      
      componentDidMount() {
        console.log(this.ARef) // {current: h1}
      }
      
      render() {
        return (
          <div>
            <NewA ref={this.ARef} words="sdfsd"/>
          </div>
        )
      }
    }
    View Code

    4 父组件调用子组件方法:

    import React, { Component, createRef } from 'react';
    
    class CustomTextInput extends Component {
      constructor(props) {
        super(props);
        this.focus = this.focus.bind(this);
      }
      focus () {
        // Explicitly focus the text input using the raw DOM API
        this.textInput.focus();
      }
    
      handleChild = () => {
        console.log('父组件调用子组件方法')
      }
    
      render () {
        // Use the `ref` callback to store a reference to the text input DOM
        // element in an instance field (for example, this.textInput).
        return (
          <div>
            <input
              type="text"
              ref={(input) => { this.textInput = input; }} />
            {/* //此时input参数就是表示该DOM本身 */}
            <input
              type="button"
              value="Focus the text input"
              onClick={this.focus}
            />
          </div>
        );
      }
    }
    
    export default class Test extends Component {
      componentDidMount () {
        console.log(this.textInput);
        //父组件自动调用子组件CustomTextInput实例的focus方法
        this.textInput.focus();
      }
    
      handleClick = () => {
        this.textInput.handleChild();
      }
    
      render () {
        return (
          <div>
            <CustomTextInput
              ref={(input) => { this.textInput = input; }} />
            <button onClick={this.handleClick}>父组件按钮</button>
          </div>
    
        );
      }
    }
    View Code

    三 useRef与createRef更新:useRef与createRef更新区别

    能够获取上一次值的原因:由于 useEffect 在 Render 完毕后才执行,因此 ref 的值在当前 Render 中永远是上一次 Render 时候的,我们可以利用它拿到上一次 Props

    import React, { useState, createRef, useRef, useEffect } from 'react';
    
    const Child1 = () => {
      const [count, setCount] = useState(0);
      const preCountUserRef = useRef();
      console.log(count);
      useEffect(() => {
        preCountUserRef.current = count;
      });
      return (
        <div>
          <p>preCount:{preCountUserRef.current}</p>
          <p>You clicked {count} times</p>
          <button onClick={() => { setCount(count + 1) }}>Click me</button>
        </div>
      )
    }
    
    export default Child1
    View Code

    useRef与createRef更新demo

  • 相关阅读:
    深入理解javascript原型和闭包(5)——instanceof
    深入理解javascript原型和闭包(4)——隐式原型
    启动mongodb的方式
    继承的几种方式
    npm install express 安装失败
    npm insta --savell和npm install --save-dev的区别
    express笔记之一安装
    mongoVUE安装配置
    nodejs笔记之一简介
    nodejs配置之二NPM配置之gulp使用时出现的错误
  • 原文地址:https://www.cnblogs.com/terrymin/p/15131927.html
Copyright © 2011-2022 走看看