目前我正在实现自己的一个组件库: 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} />
}
大家觉得哪种方案更好呢?
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.