React Refs

  1. React 支持一种非常特殊的属性 ref,可以用来绑定到 render() 输出的任何组件上;
  2. ref 的值的类型:
    1. ref 属性用于 HTML 元素时,则值是 DOM 元素
    2. ref 属性用于自定义 Class 组件 时,则值是 组件实例
  3. 函数组件上不可以使用 ref 属性,因为函数组件没有实例;

绑定 Ref 的方式

React.createRef(推荐)

  1. 通过 React.createRef() 创建出来的对象;

  2. 使用时获取到创建的对象其中有一个 current 属性就是对应的元素;

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
    // this.myRef = { current: null }; // 两种方式等价
  }

  changeText() {
    this.myRef.current.innerHTML = "hello world";
  }

  render() {
    return (
      <div>
        <h2 ref={this.myRef}>Hello Create Ref</h2>
        <button onClick={(e) => this.changeText()}>改变文本</button>
      </div>
    );
  }
}

const root = ReactDOM.createRoot(document.getElementById("root"));
// 渲染 MyComponent 组件
root.render(<MyComponent />);

回调函数

  1. 该函数会在 DOM 被挂载时进行回调,这个函数会传入一个 元素对象,可以自己保存,使用时,直接拿到之前保存的元素对象即可;

  2. 函数的调用时间:

    1. componentDidMount 的时候会调用该函数,在 componentDidMount 事件中可以使用 ref
    2. 如果 ref 的值发生了变动(旧的函数被新的函数替代),分别调用旧的函数以及新的函数,时间点出现在 componentDidUpdate 之前;
      1. 旧的函数被调用时,传递 null
      2. 新的函数被调用时,传递对象;
    3. 如果 ref 所在的组件被卸载,会调用函数;
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = null;
    this.myRef2 = null;
  }

  changeText() {
    this.myRef.focus();
    this.myRef2.focus();
    this.setState({});
  }

  getRef(el) {
    this.myRef2 = el;
  }

  render() {
    return (
      <div>
        {/* 会被调用多次,不推荐 */}
        <input ref={(el) => {
            console.log('被调用了...', el);
            this.myRef = el;
        }} type="text" />

        {/* 推荐 */}
        <input ref={(e) =>this.getRefFn(e)} type="text" />
        <button onClick={(e) => this.changeText()}>改变文本</button>
      </div>
    );
  }
}

const root = ReactDOM.createRoot(document.getElementById("root"));
// 渲染 MyComponent 组件
root.render(<MyComponent />);

字符串(不推荐)

使用时通过 this.refs.传入的字符串 格式获取对应的元素;

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

  changeText() {
    this.refs.myRef.innerHTML = "hello world";
  }

  render() {
    return (
      <div>
        <h2 ref="myRef">String Ref</h2>
        <button onClick={(e) => this.changeText()}>改变文本</button>
      </div>
    );
  }
}

const root = ReactDOM.createRoot(document.getElementById("root"));
// 渲染 MyComponent 组件
root.render(<MyComponent />);

useRef Hook

在函数组件中,可以使用 useRef Hook 创建 refs

const MyComponent = () => {
  const myRef = useRef(null);

  const changeText = () => {
    myRef.current.innerHTML = "hello world";
  };

  return (
    <div>
      <h2 ref={myRef}>String Ref</h2>
      <button onClick={(e) => changeText()}>改变文本</button>
    </div>
  );
};

const root = ReactDOM.createRoot(document.getElementById("root"));
// 渲染 MyComponent 组件
root.render(<MyComponent />);

Ref 转发

  1. ref 转发 是一种让你在组件外部调用组件内部的 DOM 元素 或者 子组件实例 的技术;

  2. 这是一个很重要的概念,尤其是在处理表单元素、处理高阶组件、DOM 操作或者管理第三方 DOM 库集成时非常有用;

  3. forwardRef 方法

    1. 参数,传递的是函数组件,不能是类组件,并且,函数组件需要有第二个参数来得到 ref
    2. 返回值,返回一个新的组件;
JavaScript
JavaScript
// 3. 函数组件:接收第二个参数,获取转发过来的 ref,并将 ref 绑定到任意元素上
function A(props, ref) {
    return <h1 ref={ref}>
        组件A
        <span>{props.words}</span>
    </h1>
}

// 1. 传递函数组件 A,得到一个新组件 NewA
const NewA = React.forwardRef(A);

class App extends React.Component {
    ARef = React.createRef()

    componentDidMount() {
        console.log(this.ARef);
    }

    render() {
        return (
            <div>
                {/* 2. 将 this.ARef 传递给 NewA 组件内部 */}
                <NewA ref={this.ARef} words="asfsafasfasfs" />
            </div>
        )
    }
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
class A extends React.Component {
    render() {
        // 4. 类组件接收自定义属性 abc,从而获取到了转发进来的 ref
        return <h1 ref={this.props.abc}>
            组件A
            <span>{this.props.words}</span>
        </h1>
    }
}

// 1. 将类组件 A 包裹后改造成函数组件,传递该函数组件,得到一个新组件 NewA
const NewA = React.forwardRef((props, ref) => {
    // 3. 将转发进来的 ref,用一个非 'ref' 的自定义属性 abc 传递给类组件
    return <A {...props} abc={ref} />
})

class App extends React.Component {
    ARef = React.createRef();

    componentDidMount() {
        console.log(this.ARef);
    }

    render() {
        return (
            <div>
                {/* 2. 将 this.ARef 传递给 NewA 组件内部 */}
                <NewA ref={this.ARef} words="asfsafasfasfs" />
            </div>
        )
    }
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. React Refs
  2. 2. 绑定 Ref 的方式
    1. 2.1. React.createRef(推荐)
    2. 2.2. 回调函数
    3. 2.3. 字符串(不推荐)
    4. 2.4. useRef Hook
  3. 3. Ref 转发