React的React.createRef()/forwardRef()源碼解析(三)


1.refs三種使用用法

ref 獲取組件或是dom節點實例 一般對於函數 不能獲取函數的實例 如果需要獲取函數的ref 則React.forwardRef方法

  1.字符串

     1.1 dom節點上使用 獲取真實的dom節點

    //使用步驟:
    1. <input ref="stringRef" />   
    2. this.refs.stringRef
    //值:節點實例對象<input />

      1.2 類組件上使用 獲取引用類組件的實例

    //使用步驟
    1. <Child ref="compStringRef" />
    2.this.refs.compStringRef
    //值:組件實例{props:{},refs:{},state:null,....}

  2.回調函數

      2.1 dom節點上掛載回調函數 函數的入參為dom節點

    //使用步驟
    1.<input ref={(ref) => { this.callBackRef = ref }} />
    2.this.callBackRef //值:<input />

      2.2 類組件上掛載回調函數 函數的參數為類組件實例

    //使用步驟
    1.<Child ref={(com) => { this.comCallbackRef = com }} />
    2.this.comCallbackRef

  3.CreateRef方法

      3.1 React.createRef()創建一個ref  賦值給一個變量 使用ref.current屬性獲取dom節點

    //使用步驟
    1.this.myCreateRef = React.createRef();
    2.<input ref={this.myCreateRef} />
    3.this.myCreateRef.current

      3.2 React.createRef()創建一個ref 賦值給一個變量 使用ref.current屬性獲取類組件實例

    //使用步驟
    1.this.myCompCreateRef = React.createRef()
    2.<Child ref={this.myCompCreateRef} />
    3.this.myCompCreateRef.current

 

2.React.forwardRef()使用用法

      1.為啥會出現forwardRef()? 

        對於純函數組件 function(props){return(<div>1111</div>)}  無法獲取ref的值  如果要獲取ref的值 必須forwardRef把ref傳遞進去

      2.獲取函數組件的實例 

   //使用步驟
   1.this.myCompCreateRef = React.createRef();
   2.<Child ref={this.myCompCreateRef} /> 
   3.this.myCompCreateRef.current
   4.const Child = React.forwardRef((props, ref) => ( //箭頭函數沒有實例 如果想獲取值 則需要forwardRef進行包裝 <input ref={ref} />
   )); //平時組件傳遞 只能傳遞props 調用forwardRef 可以傳遞第二個參數ref

 

3.React.createRef()源碼解析

  //返回一個具有current屬性的refObject對象
    function createRef() {
      var refObject = {
        current: null
      };
      {
        Object.seal(refObject);
      }
      return refObject;
    }

 

4.React.forwardRef()源碼解析

  function forwardRef(render) { //render一般指函數function組件
      {
        if (render != null && render.$$typeof === REACT_MEMO_TYPE) {
          warningWithoutStack$1(false, 'forwardRef requires a render function but received a `memo` ' + 'component. Instead of forwardRef(memo(...)), use ' + 'memo(forwardRef(...)).');
        } else if (typeof render !== 'function') {
          warningWithoutStack$1(false, 'forwardRef requires a render function but was given %s.', render === null ? 'null' : typeof render);
        } else {
          !( // Do not warn for 0 arguments because it could be due to usage of the 'arguments' object
            render.length === 0 || render.length === 2) ? warningWithoutStack$1(false, 'forwardRef render functions accept exactly two parameters: props and ref. %s', render.length === 1 ? 'Did you forget to use the ref parameter?' : 'Any additional parameter will be undefined.') : void 0;
        }

        if (render != null) {
          !(render.defaultProps == null && render.propTypes == null) ? warningWithoutStack$1(false, 'forwardRef render functions do not support propTypes or defaultProps. ' + 'Did you accidentally pass a React component?') : void 0;
        }
      }
      //返回一個對象,對象里面包含一個$$typeof屬性 它依然是ReactElement  使用時候:React.createElement(React.forwardRef(Child))
      //該對象在傳入ReactElement方法之后,保存在type屬性里 而$$typeof仍然是REACT_ELEMENT_TYPE
      return {
        $$typeof: REACT_FORWARD_REF_TYPE,
        render: render
      };
}

舉例:

import React from 'react';
//平時組件傳遞 只能傳遞props 調用forwardRef 可以傳遞第二個參數ref
const Child1 = React.forwardRef((props, ref) => {
  return <div ref={ref}> CHild2</div >
})

class Child extends React.Component {
  constructor(props) {
    super(props);
    this.myCreateRef = React.createRef();
  }
  componentDidMount() {
    setTimeout(() => {
      console.log(this.myCreateRef.current, 'onbject')
    }, 1000)
  }

  render() {
    return (
      <div>
        <Child1 ref={this.myCreateRef} />  {/*通過React.forwaedRef依然是一個ReactElement*/}
      </div>
    )
  }
}
export default Child

返回dom元素:

<div>CHild2</div >

原因:
通過調用forwardRef返回的對象{ $$typeof: REACT_FORWARD_REF_TYPE,render: render} 對應到代碼中Child1屬性為一個對象 

當調用React的creactElement(type,config[...children])函數時候 會把這個Child1屬性對象作為參數type傳遞進去 保存在type屬性中$$typeof仍然是REACT_ELEMENT_TYPE

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM