useRef、forwardRef、useImperativeHandle

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;
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值