Skip to main content

组件暴露

暴露内部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>
))