gpt4 book ai didi

javascript - 使用 Click Outside Hook 时如何防止将事件监听器多次分配给元素?

转载 作者:行者123 更新时间:2023-12-05 02:41:30 35 4
gpt4 key购买 nike

有很多版本的 click outside Hook ,它们会将“mousedown”或“touchstart”事件监听器附加到文档,并在您单击外部时关闭下拉菜单或模态窗口...

问题是,如果您有许多下拉菜单使用相同的钩子(Hook),您最终会多次将相同的事件附加到文档。

如何预防?并且只要在卸载组件时移除它们就没有关系吗?

我已经研究过,但似乎没有办法检查 dom 元素是否已经附加了事件。

示例取自:useOnClickOutside

const useOnClickOutside = (ref, handler) => {
useEffect(() => {
const listener = event => {
// Do nothing if clicking ref's element or descendent elements
if (!ref.current || ref.current.contains(event.target)) {
return;
}
handler(event);
};

const escape = event => {
if (event.keyCode === 27) {
handler(event);
}
};

// these event listeners pile up on the document if you have several component using that hook
document.addEventListener('mousedown', listener);
document.addEventListener('touchstart', listener);
document.addEventListener('keydown', escape, false);

return () => {
document.removeEventListener('mousedown', listener);
document.removeEventListener('touchstart', listener);
document.removeEventListener('keydown', escape);
};
}, [ref, handler]);
};

此处在页面上的 5 个不同下拉菜单上使用该 Hook ,将同一事件监听器分配给文档 5 次

enter image description here

最佳答案

执行此操作的最佳做​​法是使用 useEffect cleanup function

const handleMouseDown = e => {
console.log(e)
}

useEffect(() => {
document.addEventListener("mousedown", handleMouseDown)
// cleanup
return () => {
document.removeEventListener("mousedown", handleMouseDown)
}
}, [])

通过将空数组 [] 传递给 useEffect,您可以保证事件监听器仅在组件的初始安装时注册。通过使用清理功能,您可以避免多次注册它。

关于javascript - 使用 Click Outside Hook 时如何防止将事件监听器多次分配给元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68094134/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com