🔍 什么是forwardRef?
在React的世界里, forwardRef 就像是一位"引用传递大师",它能让父组件的 ref 穿过组件层级,直接触达子组件内部的DOM元素。就像你想给住在小区深处的朋友送快递, forwardRef 就是那个能帮你穿过层层门禁的神奇通道!
🤔 为什么需要forwardRef?
在本文中,这个问题体现得淋漓尽致:
// 没有forwardRef时,这行代码会报错
<Guang title="hello" ref={ref}/>
这是因为默认情况下,函数组件就像一个封闭的盒子,父组件的 ref 无法直接穿透到组件内部的DOM元素。
🛠️ forwardRef的使用方法
让我们看看项目中的示例是如何使用 forwardRef 的:
- 创建一个接收ref的组件
function Guang(props, ref) {
console.log(props, ref)
return (
<div>
<input type="text" ref={ref}/>
</div>
)
}
- 使用forwardRef包装组件
// 返回一个全新的组件, 赋予它ref向下传递的能力
// 这是一个高阶组件
const WrapperGuang = forwardRef(Guang);
- 父组件中使用包装后的组件
function App() {
// 父组件创建ref
const ref = useRef(null);
useEffect(() => {
// 聚焦到子组件中的input元素
ref.current?.focus();
},[])
return (
<div className='App'>
<WrapperGuang ref={ref}/>
</div>
)
}
🔄 forwardRef的工作原理
- 父组件通过 useRef 创建一个引用
- 这个引用被传递给 forwardRef 包装后的组件
- forwardRef 就像一个"快递员",将这个引用传递给内部的原始组件
- 原始组件将这个引用绑定到具体的DOM元素上
- 父组件就可以通过这个引用直接操作子组件中的DOM元素了
💡 forwardRef的使用场景
- 焦点控制 :就像我们的示例中那样,父组件可以直接让子组件中的输入框获得焦点
- 动画效果 :父组件可以直接访问子组件的DOM元素来应用动画
- 表单控件 :在复杂表单中,父组件可能需要直接访问子组件中的表单元素
- 高阶组件 :当你创建一个包装其他组件的高阶组件时, forwardRef 可以帮助你保持 ref 的传递链
🚫 没有forwardRef会怎样?
如果没有 forwardRef ,我们可能需要使用一些笨拙的方法来实现类似的功能,比如:
- 使用回调函数来传递DOM元素的引用
- 或者使用Context API来共享引用
- 甚至可能需要直接操作DOM,这违背了React的设计理念
🔑 关键知识点
- forwardRef 只能用于函数组件
- 包装后的组件接收 ref 作为第二个参数(第一个参数是 props )
- 父组件可以像使用普通DOM元素一样使用这个 ref
- 记得在访问 ref.current 前检查它是否存在,避免空指针错误
🎬 总结
forwardRef 是React中一个非常实用的API,它解决了函数组件无法直接接收 ref 的问题,让组件间的引用传递变得简单而优雅。
在我们的 forward-demo 项目中,通过 forwardRef ,父组件成功地将 ref 传递给了子组件中的 input 元素,并实现了自动聚焦的功能。这就是 forwardRef 的魔力!
下次当你需要从父组件访问子组件中的DOM元素时,别忘了 forwardRef 这位"引用传递大师"哦!😉