这是我使用的一个简单的下拉组件。
<script>
let show = false;
</script>
<div>
<button on:click={() => show = !show }>Show Dropdown</button>
{#if show}
<div>
<a href="/">Option 1</a>
<a href="/">Option 2</a>
<a href="/">Option 3</a>
<a href="/">Option 4</a>
</div>
{/if}
</div>
<style>
a { display: block; }
</style>
我在parent中使用了这个组件三次,如下所示:
<script>
import Dropdown from './dropdown.svelte';
</script>
<div>
<Dropdown />
<Dropdown />
<Dropdown />
</div>
一旦我点击第一个下拉菜单,其各自的下拉内容打开,但在点击下一个下拉菜单,我如何关闭以前的下拉菜单,只打开一个被点击?
谢谢
通常的方法是在顶部添加一个click
事件处理程序,并以这种方式触发关闭。你只需要排除点击发生在下拉菜单内的情况。
<script>
let show = false;
let container;
function onWindowClick(e) {
if (container.contains(e.target) == false)
show = false;
}
</script>
<svelte:window on:click={onWindowClick} />
<div bind:this={container}>
<button on:click={() => show = !show }>Show Dropdown</button>
...
</div>
REPL
(通过svelte:window
添加的事件处理程序将自动清除)
a
元素,否则可点击的东西应该是button
元素。这允许适当的键盘交互,并为屏幕阅读器提供语义。
理想情况下,元素也应该提供正确的ARIA属性(如role
),适当的键盘交互,如向上/向下箭头导航,关闭Escape等应该实现。(请参阅指南。)
我从来没有接触过苗条,但我知道如何做到这一点。
您可以使用focus
和blur
事件
您将tabindex="0"
添加到元素中,每当您打开它时,您都会聚焦元素。现在,当你点击元素外部时,模糊事件就会被触发。如果你在浏览器外点击,它甚至会被触发。
<script>
import { tick } from 'svelte';
let show = false;
let dropdownElement;
async function showDropdown() {
show = !show;
//we need to wait with tick, until DOM nodes have mounted
await tick();
dropdownElement.focus()
}
</script>
<div>
<button on:click={ showDropdown }>Show Dropdown</button>
{#if show}
<div on:blur={() => show = false} tabindex="0" bind:this={dropdownElement}>
<div>Option1</div>
<div>Option2</div>
<div>Option3</div>
</div>
{/if}
</div>
我使用div
而不是a
标签,因为当您单击a
标签时,父级将失去焦点。