【引言】页面中经常会有写全局的Modal、Alert、Toast、Login、等组件,这些组件通常会被用到很多页面中,如果每个页面都写一个Modal、Alert、Toast、Login、等组件,看起来不够美观,也不利于代码的维护。通过执行方法,即可调用全局的组件,而不需要每个页面都写一个Modal、Alert、Toast、Login、等组件。
【实现1】子组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import React, { useImperativeHandle, forwardRef, useRef } from 'react';
const ChildComponent = forwardRef((props, ref) => { const inputRef = useRef();
useImperativeHandle(ref, () => ({ focus: () => { inputRef.current.focus(); }, getValue: () => { return inputRef.current.value; } }));
return <input ref={inputRef} type="text" />; });
|
父组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import React, { useRef } from 'react'; import ChildComponent from './ChildComponent';
const ParentComponent = () => { const childRef = useRef();
const handleFocus = () => { childRef.current.focus(); };
const handleGetValue = () => { console.log(childRef.current.getValue()); };
return ( <div> <ChildComponent ref={childRef} /> <button onClick={handleFocus}>Focus Input</button> <button onClick={handleGetValue}>Get Input Value</button> </div> ); };
export default ParentComponent;
|
【实现2】1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| let captcha = null;
const Captcha = () => { const [show, setShow] = useState(false); const captchaRef = useRef(null);
useImperativeHandle(captchaRef, () => ({ show() { setShow(true); }, hide() { setShow(false); } }));
useEffect(() => { captcha = { show: () => { captchaRef.current.show(); }, hide: () => { captchaRef.current.hide(); } };
return () => { captcha = null; }; }, []);
return ( show && <div className="captcha-b" ref={captchaRef}></div> ); };
export { Captcha, captcha };
|
【总结】useImperativeHandle 是 React 中用于自定义暴露给父组件的实例值的 hook,它可以让子组件暴露给父组件方法,使得父组件可以直接调用子组件的方法。把组件挂载在根节点上,可以通过暴露出来的方法去调用。例上述方法2中,在引入captcha后,可以在组件需要的时机执行captcha.show()、captcha.hide() 方法,实现调用。