美文网首页
React 中的转发ref

React 中的转发ref

作者: JamesSawyer | 来源:发表于2018-08-06 15:26 被阅读772次

    React V16.3� 中react引入了:

    • React.forward((props, ref) => ReactComponent) 用于将组件将refs转发到子组件
    • React.createRef():创建一个ref

    这2个APIs,这对父组件中访问子组件中DOM元素提供了极大的便利

    普通的使用

    在当前组件中使用ref

    class CustomTextInput extends React.Component {
      constructor(props) {
        super(props);
        // create a ref to store the textInput DOM element
        this.textInput = React.createRef();
        this.focusTextInput = this.focusTextInput.bind(this);
      }
    
      focusTextInput() {
        // Explicitly focus the text input using the raw DOM API
        // Note: we're accessing "current" to get the DOM node
        this.textInput.current.focus();
      }
    
      render() {
        // tell React that we want to associate the <input> ref
        // with the `textInput` that we created in the constructor
        return (
          <div>
            <input
              type="text"
              ref={this.textInput} />
    
            <input
              type="button"
              value="Focus the text input"
              onClick={this.focusTextInput}
            />
          </div>
        );
      }
    }
    

    通过回调函数的形式将ref传递给子组件中的DOM中

    回调refs

    function Child(props) {
      return (
        <div>
          <input ref={props.inputRef} />
        </div>
      );
    }
    
    class Parent extends React.Component {
      
      componentDidMount() {
        if (this.textInputRef) this.textInputRef.focus();
      }
    
      render() {
        return (
          <Child inputRef={el => this.textInputRef = el}
        );
      }
    }
    

    将ref从父组件中转发到子组件中的dom元素上

    // FancyButton.js 子组件
    import React from 'react';
    
    // 接受props和ref作为参数
    // 返回一个React 组件
    const FancyButton = React.forwardRef((props, ref) => (
        <button class="fancybutton" ref={ref}>
        {props.children}
      </button>
    ));
    
    export default FancyButton;
    
    
    // 父组件
    // app.js
    class App extends React.Component {
      
      constructor(props) {
        super(props);
        // 创建一个ref 名字随意
        this.fancyButtonRef = React.createRef();
      }
      
      componentDidMount() {
        console.log('ref', this.ref);
        // this.ref.current 表示获取ref指向的DOM元素
        this.ref.current.classList.add('primary'); // 给FancyButton中的button添加一个class
        this.ref.current.focus(); // focus到button元素上
      }
      
      render() {
        // 直接使用ref={this.fancyButtonRef}
        return (
            <FancyButton ref={this.fancyButtonRef}>子组件</FancyButton>
        );
      }
    }
    

    在高阶组件中使用转发ref

    如果使用了高阶组件,还是按照上面普通的方式使用的话,会导致ref直接转发到高阶组件上,这很明显是错的,我们只需转发多次即可

    // 高阶组件
    import React from 'react';
    
    function logProps(Component) {
      class LogProps extends React.Component {
        componentDidUpdate(prevProps) {
          console.log('先前的属性:', prevProps);
          console.log('当前属性:', this.props);
        }
        
        render() {
          // 使用forwardedRef作为一个ref属性传入组件中
          const { forwardedRef, ...rest } = this.props;
          return (
            <Component ref={forwardedRef} {...rest} />
          );
        }
      }
      
      // 使用React.forwardRef对LogProps组件进行转发
      return React.forwardRef((props, ref) => (
        {' 上面定义的LogProps组件接受一个forwarded属性 '}
        <LogProps forwardedRef={ref} {...props} />
      ));
    }
    
    
    
    // FancyButton.js 子组件
    import React from 'react';
    import logProps from './logProps';
    
    // 接受props和ref作为参数
    // 返回一个React 组件
    const FancyButton = React.forwardRef((props, ref) => (
        <button class="fancybutton" ref={ref}>
        {props.children}
      </button>
    ));
    
    // 使用高阶组件对其进行封装
    export default logProps(FancyButton);
    
    
    // 父组件
    // app.js
    class App extends React.Component {
      
      constructor(props) {
        super(props);
        // 创建一个ref 名字随意
        this.fancyButtonRef = React.createRef();
      }
      
      componentDidMount() {
        console.log('ref', this.ref);
        // this.ref.current 表示获取ref指向的DOM元素
        this.ref.current.classList.add('primary'); // 给FancyButton中的button添加一个class
        this.ref.current.focus(); // focus到button元素上
      }
      
      render() {
        // 直接使用ref={this.fancyButtonRef}
        return (
            <FancyButton ref={this.fancyButtonRef}>子组件</FancyButton>
        );
      }
    }
    

    可以看出如果需要使用高阶组件,则在高阶组件中也需要对其进行转发。

    相关文章

      网友评论

          本文标题:React 中的转发ref

          本文链接:https://www.haomeiwen.com/subject/gkxgvftx.html