我已经实现了点击外钩以关闭文档mousedown
上的菜单组件:
const useClickOutside = onClickOutside => {
const ref = useRef(null);
useEffect(
() => {
const handleClickOutside = e => {
if (ref.current && !ref.current.contains(e.target)) {
onClickOutside(e);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
},
[onClickOutside, ref]
);
return ref;
};
菜单的输入附加了onBlur
事件处理程序:
const Input = ({ onValueEnter }) => {
const [value, setValue] = useState("");
const handleValueChange = e => setValue(e.target.value);
const handleBlur = () => onValueEnter(value);
return (
<input onBlur={handleBlur} value={value} onChange={handleValueChange} />
);
};
const Menu = ({ onClose }) => {
const ref = useClickOutside(onClose);
return (
<div ref={ref} className="menu">
<h1>Enter value</h1>
<Input onValueEnter={handleValueEnter} />
</div>
);
};
问题是,如果我将焦点放在输入并在菜单外单击,则输入上的onBlur
事件永远不会触发。 Codesandbox示例在这里。
显然,由于react
通过将事件附加到顶层而不是实际的dom节点来实现了自己的事件委托系统,因此全局事件处理程序(如在document.addEventListener
中注册的事件处理程序)在react事件之前运行处理程序(github issue)。
所以我的问题是,如何解决这个问题?甚至有可能使onBlur
事件处理程序首先运行,然后再运行全局事件处理程序吗?
编辑:我已经在setTimeout
内部使用onClose
进行黑客攻击,以使其暂时起作用,但我真的想避免使用它,而是找到一种更好的解决方案。
答案 0 :(得分:0)
我一起砍了一些东西使其工作。它围绕着在关闭时使用forwardRef和imperativeHandle从child访问值的方法。我不知道这是否能解决您的问题。