forwardRef官方文档
useImperativeHandle
forwardRef
forwardRef让你的组件通过 ref 向父组件公开 DOM 节点,ref
不像props
作为参数可以传递,所以要想传递ref
得用forwardRef
用法:
const SomeComponent = forwardRef(render)
-
render:组件的渲染函数。React 使用ref组件从其父级收到的
props
和 调用此函数。 -
forwardRef返回一个可以在 JSX 中渲染的 React 组件。与定义为普通函数的 React 组件不同,返回的组件
forwardRef
还能够接收ref
的prop
。
案例1:获取子组件dom,使其聚焦
使用forwardRef
使ref组件接收到父组件的props和ref,点击focus按钮,获取到子组件的dom,然后执行dom的.current.focus()
的方法实现聚焦。
import { useRef, forwardRef } from "react";
const Son = forwardRef((props,ref)=>{
return <input type="text" ref={ref} />
})
function App() {
const sonRef = useRef(null);
const showRef = ()=>{ console.log(sonRef);sonRef.current.focus();}
return (
<div className="App">
<Son ref={sonRef} />
<button onClick={showRef}>focus</button>
</div>
);
}
export default App;
打印出子组件的dom如下
useImperativeHandle
在父组件调用子组件本身的成员方法,子组件通过useImperativeHandlef
暴露出子组件的方法。
用法:
useImperativeHandle(ref, createHandle, dependencies?)
-
ref:父组件传过来的ref,也就是从forwardRef包裹的渲染函数收到的第二个参数(要和forwardRef渲染函数里的第二个参数对应 )
-
createHandle:公开暴露的方法。返回值就是我们要传给父组件的方法和属性,返回的是一个对象
-
可选 dependencies:依赖项。只有依赖项中的值发生改变,才会把最新的属性和方法传给父组件;如果没有依赖项,则表示只要子组件render都会把属性和方法传给父组件
//useCallback
import { useState, useRef,useImperativeHandle, forwardRef } from "react";
const Son = forwardRef((props, ref) => {
//视线聚焦逻辑
const inputRef = useRef(null);
const focusHandler = () => {
inputRef.current.focus();
}
//方法暴露出去
useImperativeHandle(ref,()=>{
return {focusHandler}
})
return <input type="text" ref={inputRef} />
})
function App() {
const sonRef = useRef(null);
const focusHandler = () => {
console.log(sonRef);
sonRef.current.focusHandler();
}
return (
<div className="App">
<Son ref={sonRef} />
<button onClick={focusHandler}>focus</button>
</div>
);
}
export default App;