useRef

  • useRef 返回一个可变的 ref 对象,其.current属性被初始化为传入的参数(initialValue)
  • 返回的 ref 对象在组件的整个生命周期内保持不变

forwardRef

  • 将ref从父组件中转发到子组件中的dom元素上
  • 子组件接受props和ref作为参数

useImperativeHandle

  • useImperativeHandle可以让你在使用 ref 时自定义暴露给父组件的实例值
  • 在大多数情况下,应当避免使用 ref 这样的命令式代码。useImperativeHandle 应当与 forwardRef 一起使用
  • 其函数签名与 useEffect 相同,但它会在所有的 DOM 变更之后同步调用 effect
  • 可以使用它来读取 DOM 布局并同步触发重渲染
  • 在浏览器执行绘制之前useLayoutEffect内部的更新计划将被同步刷新
  • 尽可能使用标准的 useEffect 以避免阻塞视图更新
import React, { useEffect, useState, useRef, forwardRef, useImperativeHandle, useLayoutEffect } from 'react';

//useEffect的销毁
function Counter1() {
    let [state, setState] = useState({ number: 0 });
    //useEffect里面方法会有返回值,返回值是一个函数,一般用来执行清理动作
    //每次执行effect之前都会执行此unEffect函数
    useEffect(() => {
        let $timer = setInterval(() => {
            setState(prevState => ({ number: prevState.number + 1 }));
        }, 1000);
        return () => {
            clearInterval($timer);
        }
    }, []);
    return (
        <div>
            <p>{state.number}</p>
            <button onClick={() => setState(prevState => ({ number: prevState.number + 1 }))}>+</button>
        </div>
    )
}

//一定是第个参数
function Child(props, parentRef) {
    let inputRef = useRef();
    useImperativeHandle(parentRef, () => (
        {
            focus() {
                inputRef.current.focus();
            },
            setValue(newVal) {
                inputRef.current.value = newVal;
            }
        }
    ));
    return (
        <>
            <input type="text" ref={inputRef} />
        </>
    )

}
let ForwardedChild = forwardRef(Child);
function Parent() {
    let [number, setNumber] = useState(0);
    let parentRef = useRef();//{current:null} //每次都会返回同一个对象
    function getFocus() {
        //希望在父组件只能调用focus方法,其它的方法都不能调用
        parentRef.current.focus();//current是此input框 的真实DOM元素
        //inputRef.current.value = 'something';
        parentRef.current.setValue('something');
    }
    return (
        <>
            <ForwardedChild ref={parentRef} />
            <button onClick={() => setNumber(prevState => prevState + 1)}>+</button>
            <button onClick={getFocus}>获得焦点</button>
        </>
    )

}

function Counter3() {
    let [color, setColor] = useState('red');
    useLayoutEffect(() => {
        console.log("useLayoutEffect", document.getElementById('myDiv').style.backgroundColor);
        alert('useLayoutEffect' + color);
    });
    useEffect(() => {
        console.log("useEffect", document.getElementById('myDiv').style.backgroundColor);
        alert('useEffect' + color);
    });
    return (
        <>
            <div id="myDiv" style={{ backgroundColor: color }}>颜色</div>
            <button onClick={() => setColor('red')}>红</button>
            <button onClick={() => setColor('yellow')}>黄</button>
            <button onClick={() => setColor('blue')}>蓝</button>
        </>
    )

}
export default Counter3;

带你入门前端
38 声望2 粉丝

通俗易懂,言简意赅授课