我在 svelteKit
中遇到了碰撞问题。该按钮打开菜单,但当我尝试关闭它时,它没有。当我在按钮外部单击时,这会触发调用 clickOutside.js
的 handleClickOutside
,然后关闭菜单。
我认为问题在于 element.contains
包含按钮,因此菜单没有关闭。
但是,我无法修复它。
我正在使用 tailwindUI
、tailwindCSS
、SvelteKit
。
index.svelte
<script>
// @ts-nocheck
import bostonLogo from '../../img/bostonLogo.png';
import { clickOutside } from '../../lib/clickOutside';
// Example Profile
let profile = {
name: 'Matias',
lastName: 'Barletta'
};
// Show/Hide Menu
let menu = false;
// COLLISION WITH HANDLENAV
function handleClickOutside(event) {
menu = false;
}
function handleNav() {
menu = !menu;
}
</script>
<div>
<!-- Static sidebar for desktop -->
<div class=" md:flex md:w-64 md:flex-col md:fixed md:inset-y-0" class:hidden={!menu}>
<!-- Sidebar component, swap this element with another sidebar if you like -->
<div
use:clickOutside
on:click_outside={menu? handleClickOutside : ''}
class:absolute={menu}
class:mt-11={menu}
class="md:flex-1 md:flex md:flex-col md:min-h-0 bg-gray-800"
>
...
clickOutside.js
// @ts-nocheck
/** Dispatch event on click outside of element */
// @ts-ignore
export function clickOutside(element) {
// @ts-ignore
const handleClick = (event) => {
console.log(event.target, document.body)
// element exist?, element contain where i did click, preventDefault = false?
if (element && !element.contains(event.target) && !event.defaultPrevented) {
element.dispatchEvent(
// Dispatch and create new custom event.
new CustomEvent('click_outside', element)
);
}
};
// add eventlistener when you click on document
document.addEventListener('click', handleClick, true);
return {
destroy() {
document.removeEventListener('click', handleClick, true);
}
};
}
最佳答案
不久前我遇到了完全相同的问题。我的解决方案是在菜单打开时忽略菜单点击。你已经有了这个:on:click_outside={menu? handleClickOutside : ''}
.
所以现在如果菜单关闭,则不会触发该操作。如果菜单打开,则菜单按钮不会触发。所以总是只有 1 个回调被调用。
function handleNav() {
if (menu) return;
menu = !menu;
}
作为替代方案,您可以向操作添加选项,以便如果目标在被忽略的选择器列表中(而不仅仅是它所在的元素),handleClick
函数可以忽略点击。
更新
此处的替代方法是 working REPL .
我们所做的,是为菜单按钮添加一个 ID
<button
id="menu-button"
type="button"
value="button"
class="-ml-0.5 -mt-0.5 h-12 w-12 inline-flex items-center justify-center rounded-md text-gray-500 hover:text-gray-900 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500"
on:click={handleNav}
>...</button>
然后我们将该 ID 作为参数添加到 use:clickOutside
操作中:
<div
use:clickOutside={{ignore: 'menu-button'}}
on:click_outside={menu? handleClickOutside : ''}
class:absolute={menu}
class:mt-11={menu}
class="md:flex-1 md:flex md:flex-col md:min-h-0 bg-gray-800"
>
<div class="h-40 w-40 bg-slate-600 p-3 text-white">
Some menu content here
</div>
</div>
然后在操作中,我们通过 ID 获取元素并检查我们是否在其中。
const handleClick = (event) => {
event.preventDefault();
// This function kinda rearranged with early returns to take the new parameter into account.
if (!element) return;
if (element.contains(event.target)) return;
//Get the element based on the id we gave in the params
const ignore = document.getElementById(opts.ignore)
//Check that we're not clicking in the button.
if (ignore.contains(event.target)) return;
element.dispatchEvent(
// Dispatch and create new custom event.
new CustomEvent('click_outside', element)
);
};
关于javascript - 如何解决两个事件之间的碰撞,单击外部并单击按钮以关闭 svelte 工具包中的菜单?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72815328/