天天看點

createRef和useRef差別——useRef的使用——forwardRef完成類元件的綁定—— useImperativeHandle——映射ref對象——更新同步

useRef簡單的使用

const usernameUseRef = useRef()
  <input type="text" ref={usernameRef} />
     <button
       onClick={() => {
         console.log(usernameRef.current.value)
       }}
     >      

createRef和useRef差別

  • createRef 它可以用在類元件和函數元件中,聲明式不能給初始值
  • ​ const usernameCreateRef = createRef()​

  • useRef 它隻能使用在函數元件中,useRef它可以在聲明時給初始值,但一般為null
  • ​const usernameUseRef = useRef(null)​

  • createRef每次重新渲染時都會建立一個ref對象,元件被重新渲染時它也會重新建立,但是因為類元件中它有生命周期,我可以在構造函數中建立這個ref,也就會執行一次。
  • useRef第1次渲染時建立一個對象之後,再新渲染時,如果發現這個對象已經存在過不會再建立,它的性能更好一些,在函數元件中推薦使用useRef
createRef和useRef差別——useRef的使用——forwardRef完成類元件的綁定—— useImperativeHandle——映射ref對象——更新同步

測試:驗證;

import React, { createRef, useRef, useEffect, useState } from 'react';

const App = () => {
    const usernameCreateRef = createRef();
    const usernameuseRef = useRef();

    const [value, setvalue] = useState(100)
    if (!usernameCreateRef.current) {
        usernameCreateRef.current = value;
    }
    if (!usernameuseRef.current) {
        usernameuseRef.current = value;
    }

    return (
        <div>

            <hr />
            <h1>
                createRef:{usernameCreateRef.current}
            </h1>
            <h1>
                useRef:{usernameuseRef.current}
            </h1>
            <hr />
            <h1>

            </h1>
            <button onClick={
                () => {
                    setvalue(v => v + 1)
                }
            }>++++</button>
        </div>
    );
}

export default App;      

forwardRef完成類元件的綁定

  • 如果ref對象綁定在自定義類元件中,則得到目前自定義類元件的執行個體,進而可以實作元件通信
  • 如果ref直接綁定在自定義函數元件中,則不行,因為函數元件沒有執行個體,是以會報錯
  • 函數元件如果你需要綁定ref,則需要通過它提供的一個頂層api方法來增強函數元件進而實作函數元件也可以綁定ref對象​

    ​React.forwardRef​

  • 直接使用ref的話就會報錯
  • createRef和useRef差別——useRef的使用——forwardRef完成類元件的綁定—— useImperativeHandle——映射ref對象——更新同步
    createRef和useRef差別——useRef的使用——forwardRef完成類元件的綁定—— useImperativeHandle——映射ref對象——更新同步
  • 通過這個​

    ​forwardRef​

    ​來包裹一下這個子元件就行。

    就可以ref了,具體還得往下看。

createRef和useRef差別——useRef的使用——forwardRef完成類元件的綁定—— useImperativeHandle——映射ref對象——更新同步
import React, { useRef,forwardRef } from 'react';

const Child = forwardRef((props,_ref) => {

    return (
        <div>
            <h1 ref={_ref}>子元件</h1>
        </div>
    );
})

const App = () => {
    const ref = useRef();
    return (
        <div>
            <Child ref={ref}/>
            <button onClick={e=>{
                console.log(ref.current);
            }}>@@@@@</button>
        </div>
    );
}
export default App;      
const ref = useRef(100);      
const App = () => {
    const ref = useRef(100);
    return (
        <div>
            <Child ref={ref}/>
            <button onClick={e=>{
                ref.current++
                console.log(ref.current);
            }}>@@@@@</button>
        </div>
    );
}
export default App;      

useImperativeHandle映射對象(透傳)

useImperativeHandle(_ref,()=>{
    return {
        value,
        changevalue,
        childref
    }
})      
  • 參數1:就是父元件傳過來的ref對象
  • 參數2:回調函數,傳回一個對象,穿透給父元件的資料
import React, { useRef,forwardRef, useState ,useImperativeHandle} from 'react';

const Child = forwardRef((props,_ref) => {
    let [value,setValue] = useState();
    const changevalue = (newvalue)=>{
        setValue(newvalue)
    }
    const childref = useRef()
    useImperativeHandle(_ref,()=>{
        return {
            value,
            changevalue,
            childref
        }
    })

    return (
        <div>
            <h1>子元件</h1>
            <input type="text" name="" id="" ref={childref} value="123s"/>
            <h2>{value}</h2>
        </div>
    );
})

const App = () => {
    const ref = useRef(100);
    return (
        <div>
            <Child ref={ref}/>
            <hr />
            <button onClick={e=>{
            //    擷取到傳回來的映射對象,操作子元件的内容
            console.log(ref.current);
            ref.current.changevalue("niupeng")
            }}>@@@@@</button>
        </div>
    );
}
export default App;      

useLayouEffect同步周期函數

import React, { useLayoutEffect, useEffect } from 'react'

const App = () => {

  // js事件循環中,同步優先于異步

  // 異步
  useEffect(()=>{
    console.log('useEffect');
  },[])

  // 同步  如果你是操作dom來說,建議用它
  useLayoutEffect(()=>{
    console.log('useLayoutEffect');
    document.title = '你好react'
  },[])
 

  return <div>
    <h3>App元件</h3>
  </div>
}

export default      

繼續閱讀