前端与react | 青训营笔记

23 阅读2分钟

这是我参与第五届青训营伴学笔记创作活动的第四天

ref的高阶用法

1.forwardRef转发ref

forwardRef 接受了父级元素标记的 ref 信息,并把它转发下去,使得子组件可以通过 props 来接受到上一层级或者是更上层级的ref

使用场景:

  • 跨层级获取(爷组件想要获取孙组件的一个Node实例)
  • 合并转发ref
  • 高阶组件的转发

2.ref实现组件通信

使用场景

  • 类组件ref(直接通过ref获取即可)
  • 函数组件(通过forwardRef+useImperativeHandle)(因为函数组件没有实例)
// 子组件
function Son (props,ref) {
    const inputRef = useRef(null)
    const [ inputValue , setInputValue ] = useState('')
    useImperativeHandle(ref,()=>{
       const handleRefs = {
           onFocus(){              /* 声明方法用于聚焦input框 */
              inputRef.current.focus()
           },
           onChangeValue(value){   /* 声明方法用于改变input的值 */
               setInputValue(value)
           }
       }
       return handleRefs
    },[])
    return <div>
        <input placeholder="请输入内容"  ref={inputRef}  value={inputValue} />
    </div>
}

const ForwarSon = forwardRef(Son)
// 父组件
class Index extends React.Component{
    cur = null
    handerClick(){
       const { onFocus , onChangeValue } =this.cur
       onFocus() // 让子组件的输入框获取焦点
       onChangeValue('let us learn React!') // 让子组件input  
    }
    render(){
        return <div style={{ marginTop:'50px' }} >
            <ForwarSon ref={cur => (this.cur = cur)} />
            <button onClick={this.handerClick.bind(this)} >操控子组件</button>
        </div>
    }
}

3.函数组件缓存数据

原理:useRedf可以创建出一个ref原始对象,只要组件不销毁,ref对象一直存在,因此可以将不依赖于视图更新的数据存储到ref对象中

Ref的原理

逻辑流程图

只有当fiber初始化时或者ref对象的指向改变的时候,会执行这一逻辑更新图。


更新是同步还是异步

batchUpdate批量更新,异步并不是使用了Promise等异步方法,其实本身执行的过程和代码都是同步的,但是合成事件和生命周期的调用顺序在更新之前,导致没法立刻拿到更新后的值,形成了形式上的异步

内部通过一个变量——isBatchingUpdates来判断是否批量更新

持续更新~~

总结

  1. setState只是在合成事件和生命周期中是异步的,在原生事件和setTimeout中都是同步的(例如通过addEventListener监听事件)