likes
comments
collection
share

react - 10.useImperativeHandle

作者站长头像
站长
· 阅读数 13

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