目录:
- 简介
- useRef
- forwardRef
简介
大家都知道React中的ref
属性可以帮助我们获取子组件的实例或者Dom对象,进而对子组件进行修改,是一个很方便的特性。在传统类组件中,我们通过使用 React.createRef()
创建的,并通过 ref
属性附加到 React 元素来使用。而随着hooks的越来越广泛的使用,我们有必要了解一下在函数式组件中,如何使用Ref.
想要在函数式组件中使用Ref
,我们必须先了解两个Api,useRef
和forwardRef
useRef
const refContainer = useRef(initialValue);
useRef返回一个可变的ref
对象,其.current
属性被初始化为传入的参数(initialValue)
。返回的ref
对象在整个生命周期内保持不变。 下面看一个例子
function TextInputWithFocusButton() {
// 关键代码
const inputEl = useRef(null);
const onButtonClick = () => {
// 关键代码,`current` 指向已挂载到 DOM 上的文本输入元素
inputEl.current.focus();
};
return (
<>
// 关键代码
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}
当我们点击button,先通过useRef创建一个ref对象inputEl,然后再将inputEl赋值给input的ref,最后,通过inputEl.current.focus()就可以让input聚焦。 然后,我们再想下,如果input不是个普通的dom元素,而是个组件,该怎么办呢? 这就牵扯到另外一个api,forwardRef
。
forwardRef
我们修改一下上面的例子,将input
单独封装成一个组件TextInput
。
const TextInput = forwardRef((props,ref) => {
return <input ref={ref}></input>
})
然后用TextInputWithFocusButton
调用它
function TextInputWithFocusButton() {
// 关键代码
const inputEl = useRef(null);
const onButtonClick = () => {
// 关键代码,`current` 指向已挂载到 DOM 上的文本输入元素
inputEl.current.focus();
};
return (
<>
// 关键代码
<TextInput ref={inputEl}></TextInput>
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}
可以看到React.forwardRef
接受一个渲染函数,其接收 props
和 ref
参数并返回一个 React 节点。 这样我们就将父组件中创建的ref
转发进子组件,并赋值给子组件的input
元素,进而可以调用它的focus
方法。 至此为止,通过useRef+forwardRef
,我们就可以在函数式组件中使用ref
了。当然,还有两个重要的知识点useImperativeHandle
:只需暴露父组件需要的值和方法,不用暴露整个子组件。回调Ref
:父组件能获取子组件实时的值。