【问题标题】:Close other dropdown on click in svelte在 svelte 中单击时关闭其他下拉菜单
【发布时间】:2022-07-08 05:35:15
【问题描述】:

这是我使用的简单下拉组件。 repl here

<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>

我在父级中使用这个组件三次如下:

<script>
    import Dropdown from './dropdown.svelte';
</script>

<div>
    <Dropdown />
    <Dropdown />
    <Dropdown />
</div>

一旦我点击第一个下拉菜单,其相应的下拉菜单内容就会打开,但在点击下一个下拉菜单时,如何关闭之前的下拉菜单并只打开被点击的下拉菜单?

谢谢

【问题讨论】:

    标签: javascript svelte sveltekit


    【解决方案1】:

    为此,一种常见的方法是在顶部添加一个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 等键盘交互。 (See guidelines.)

    【讨论】:

    • 同意,为了屏幕阅读器和易用性,最好保持标签完整,谢谢
    • 你可以使用&lt;svelte:window&gt;而不是依赖onMountdocument.addEventListener
    • @StephaneVanraes:是的,稍微简化了代码,谢谢
    【解决方案2】:

    好吧,我从来没有接触过苗条,但我知道如何做到这一点。

    您可以使用focusblur 事件

    您将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 标记时,父级会失去焦点。

    【讨论】:

    • 为特定任务使用正确的元素对于可访问性很重要。这是一种 hack,可防止通过键盘与选项进行交互,并且屏幕阅读器之类的东西缺乏有关元素代表的关键信息。
    猜你喜欢
    • 1970-01-01
    • 2012-12-19
    • 1970-01-01
    • 2018-02-06
    • 1970-01-01
    • 1970-01-01
    • 2021-11-17
    • 1970-01-01
    相关资源
    最近更新 更多