目前我正在实现自己的一个组件库: https://agile-ui.vercel.app/
里面用到了 useFocus, useHover 等等自定义的 Hook
目前这种机制的 Hook 有两种实现方式:
第一种: 传入原始的 onBlur, onFocus 事件,然后合并事件并返回 handle ,在组件里面使用 on 绑定:
export const useFocus = (options) => {
const { state = false, onBlur, onFocus } = options;
const [focus, setFocus] = useState(state);
const handleBlur = useCallback(
(e) => {
setFocus(false);
onBlur && onBlur(e);
},
[onBlur]
);
const handleFocus = useCallback(
(e) => {
setFocus(true);
onFocus && onFocus(e);
},
[onFocus]
);
return { focus, handleBlur, handleFocus };
}
export const Demo = (props) => {
const { onBlur, onFocus, ...rest } = props;
const { focus, handleBlur, handleFocus } = useFocus({ onBlur, onFocus });
return <button onBlur={handleBlur} onFocus={handleFocus} {...rest} />
}
第二种:利用 ref 绑定事件即可,不需要传递事件
export const useFocus = () => {
const [focus, setFocus] = useState(false);
const ref = useRef(null);
const handleBlur = useCallback(() => setFocus(false), []);
const handleFocus = useCallback(() => setFocus(true), []);
useEffect(() => {
if (ref.current) {
ref.current.addEventListener('blur', handleBlur);
ref.current.addEventListener('focus', handleFocus);
return () => {
ref.current?.removeEventListener('blur', handleBlur);
ref.current?.removeEventListener('focus', handleFocus);
};
}
return undefined;
}, []);
return { ref, focus };
}
export const Demo = (props) => {
const { ref, focus } = useFocus();
return <button ref={ref} {...props} />
}
大家觉得哪种方案更好呢?
1
XCFOX 2022-08-10 23:01:53 +08:00
ref ,并且这个 ref 得支持从外部传入。
如果返回 bind 绑定的话,可能会出现多个 hook 的 bind 对应到同一个 element 的同一个事件。 比如 useDrag() 和 useHover() 同时绑定了目标元素的 onMouseEnter 事件。 |
2
Leviathann 2022-08-10 23:31:10 +08:00
目前业内用的比较多的是 2
|
3
runtousa 2022-08-11 08:30:21 +08:00 via iPhone
文档写的挺好的
|
4
dog 2022-08-11 08:56:10 +08:00
可以看看 ahooks ,他们实现了很多自定义的 hook
https://github.com/alibaba/hooks |
5
Mutoo 2022-08-11 09:48:34 +08:00
第一种更容易 compose handle functions ,如果用户需要额外的逻辑的话,第二种就没办法实现了。
|
6
huijiewei OP 感谢大家的回复。最终使用第二种方案,利用 useMergeRefs 的能力,合并 handle 也非常简单
|
7
juneszh 2022-08-11 12:31:33 +08:00
ref
|