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

在这里插入图片描述
测试:验证;

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的话就会报错
    在这里插入图片描述
    在这里插入图片描述
    通过这个forwardRef来包裹一下这个子组件就行。
    就可以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;

当然通过这个useref可以初始化的特性,ref也可以完成对组件的传值。

 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 集合useRef和forwardRef 方法来模拟给函数组件绑定ref对象来得到子组件中对外暴露出来的方法或数据

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 App

猜你喜欢

转载自blog.csdn.net/m0_46672781/article/details/127231701