useImperativeHandle 这个Hook的作用。
官方解释:useImperativeHandle 是 React 中的一个 Hook,它能让你自定义由 ref 暴露出来的句柄。
官方中提到了ref,可以知道这个 Hook (钩子,后续我说的Hook===钩子)是用来联动其它的Hook的一个作用,也就是联动开发中十分常用的useRef 钩子,如果有需要useImperativeHandle的场景,则必须使用上useRef或者ref。
官方的给出了示例代码,我就直接按照示例代码来做笔记:
首先给出我的总结:可以自定义的将子组件的方法剥离出来,给父组件用,而不是给父组件一个完整的 dom对象,更加安全更加舒服的处理命令式操作。
文件结构为:
- App.jsx; (父组件)
- MyInput.jsx;(子组件)
App.jsx
import { useRef } from 'react';
import MyInput from './MyInput.js';
export default function Form() {
const ref = useRef(null);
// 注意:这里的ref不是MyInput这个组件的dom对象,这个组件返回的dom对象是inputRef的
function handleClick() {
ref.current.focus();
// 下方代码不起作用,因为 DOM 节点并未被暴露出来:
ref.current.style.opacity = 0.5;
}
return (
<form>
<MyInput placeholder="Enter your name" ref={ref} />
<button type="button" onClick={handleClick}>
Edit
</button>
</form>
);
}
MyInput.jsx
import { useRef, useImperativeHandle } from 'react';
function MyInput({ ref, ...props }) {
const inputRef = useRef(null);
// 注意:这里的inputRef才是input的dom对象,而ref是个劫匪抢掉了一些inputRef的功能。
useImperativeHandle(ref, () => {
return {
focus() {
inputRef.current.focus();
},
scrollIntoView() {
inputRef.current.scrollIntoView();
},
};
}, []);
return <input {...props} ref={inputRef} />;
};
export default MyInput;
如果我还是看不懂,可能是把两个ref搞混了,那打印对应的结果看看:
| 打印的位置与对象 | 打印结果 |
|---|---|
| myinput.jsx inputRef | current: input |
| myinput.jsx ref: | current: focus: ƒ focus(); scrollIntoView: ƒ scrollIntoView() |
| App.jsx ref | current: focus: ƒ focus() ; scrollIntoView: ƒ scrollIntoView() |
可以看到子组件中的input输入框自始至终都没有暴露给父组件使用,父组件用useRef获取的只有子组件中两个功能 focus()和scrollIntoView(),这样成功控制了父组件的权限,或者说控制了子组件暴露出来的权柄。
官方还给出了一个功能,暴露你自己的命令式方法,其实就是搭积木,更加灵活一点,理解第一个方法,这个第二个一看就懂了。
最后附上官方文档useImperativeHandle – React 中文文档