react - 10.useImperativeHandle
1.useImperativeHandle的作用:
通过useRef方法,ref可以拿到子组件的完整实例以及所有的方法,所有的属性,虽然这种方式很方便,但是缺点也很明显,比如这样做会全面暴露组件内部的api,从额头导致在外部使用api时会有更大的自由度,这其实并不是好事,因为这样会提高组件的使用难度,所以这种方式在实际开发中是不推荐的
我们应该严格控制ref的暴露颗粒度,我们只需要暴露需要用到的功能函数,其他功能函数不暴露,React官方提供了useImperativeHandle这个方法
2.useImperativeHandle语法:
useImperativeHandle(ref, createHandle, [deps])
ref:定义current对象的ref属性
createHandle:这是一个函数,返回值是一个对象,即这个ref的current对象
[deps]:依赖列表。当监听的依赖发生变化时,useImperativeHandle才会重新将子组件的实例属性输出到父组件ref的current属性上,如果为空数组,则不会重新输出
3.例子:配合forwardRef和useRef在根组件获取子组件传过来的ref对象,使用useImperativeHandle定义将哪些函数或者属性暴露给外部访问
import { forwardRef, useRef, useState, useImperativeHandle } from 'react'
const InputCom = forwardRef((props: any, ref: any) => {
const onChange = (event: any) => {
// 获取表单输入的值
const value = event.currentTarget.value
console.log(value)
props.onChange(value)
}
useImperativeHandle(ref, () => {
return {
// 想要通过子组件ref暴露的方法
focus: () => (ref.current as HTMLInputElement).focus(),
onChange
}
}, [props.value])
return (
<input
type="text"
ref={ref}
onChange={onChange}
value={props.value}
placeholder={props.placeholder}
/>
)
})
const App = () => {
const inputRef = useRef(null)
const [queryKey, setQueryKey] = useState("")
const [placeholder, setPlaceholder] = useState("请输入搜索内容")
const onQuery = () => {
const from = { queryKey }
console.log(from)
console.log(inputRef)
}
const onClean = () => {
setQueryKey("");
(inputRef.current as any)?.focus()
}
return (
<div>
<InputCom ref={inputRef} onChange={setQueryKey} value={queryKey} placeholder={placeholder}></InputCom>
<button type='button' onClick={onQuery}>search</button>
<button type='button' onClick={onClean}>reset</button>
</div>
)
}
export default App
通过这个例子,我们发现,当我们通过useImperativeHandle方法指定暴露出哪些方法的时候,当父组件获取子组件ref,就会看到我们所设置的,如果去掉useImperativeHandle方法,我们获取子组件ref的时候,会发现看到所有的对象方法
4.useImperativeHandle使用注意事项:
1.useImperativeHandle和React.forwardRef必须配合使用,否则在运行的时候会直接报错
2.使用useImperativeHandle后,可以让父子组件分别有自己的ref,通过React.forwardRef将父组件的ref传递过来,通过useImperativeHandle方法来自定义开放给父组件current
转载自:https://juejin.cn/post/7236249064542404665