组件暴露
暴露内部API - forwardRef
forwardRef
的设计实现了既保持函数组件的简洁性,又能满足复杂的组件交互需求,特别适合需要高复用性的组件开发场景。
场景 | 使用 forwardRef | 不使用 forwardRef |
---|---|---|
父组件访问子组件 DOM | ✔️ 可访问内部元素 | ❌ 得到组件外壳 div |
暴露自定义方法 | ✔️ 通过 useImperativeHandle | ❌ 无法暴露方法 |
函数组件 ref 接收 | ✔️ 正确接收 | ❌ 收到警告/错误 |
TypeScript 支持 | ✔️ 完整类型推断 | ❌ 类型不匹配 |
// 语法模板
const 组建名称 = forwardRef<对位暴露的类型, 接收的props类型>(
(props, ref) => {
// 组件实现...
}
)
// 核心语法
const DraggableElement = forwardRef<DraggableElementHandle, DraggableElementProps>(
(props, ref) => {
// 组件实现...
useEfect(()=>{})
// 配合useImperativeHandle来对外暴露api
useImperativeHandle(ref, () => ({
getMoveDistance: () => [position.x, position.y],
parentElement: parentRef.current,
}));
},
)
外部调用
<DraggableElement ref={draggableRef}>
forwardRef<暴露的类型, Props类型>(...)
定义暴露API - useImperativeHandle
场景 | 使用 useImperativeHandle | 不使用 useImperativeHandle |
---|---|---|
ref 获得的内容 | 自定义对象(指定暴露的方法) | 默认获得 DOM 节点引用 |
类型安全 | 严格类型检查 | 无类型约束 |
组件封装性 | 高,内部实现完全隐藏 | 低,可直接操作 DOM |
方法访问 | 通过 ref.current.method() 调用 | 无法直接访问组件方法 |
// 获取移动距离
draggableRef.current?.getMoveDistance() // 返回 [x, y]
// 访问父容器
draggableRef.current?.parentElement // 获取 DOM 元素
穿透ref - 获取内部ref
const Input = forwardRef((props, ref) => (
<div>
<input ref={ref} {...props} />
</div>
))