如何在 <svelte:this> 递归文件夹树上使用 isActive class?

How to use an isActive class on <svelte:this> recurisve folder tree?

我正在构建递归文件夹结构,希望能够通过切换 class 来突出显示单击的文件夹。以便用户知道他们点击了哪个文件夹。

我已经成功完成了,但是当使用 sveltes 递归元素时 <svelte:this> 没有按预期工作。似乎每个递归文件夹都在它自己的范围内。

错误的结果是每个文件夹突出显示都是自己的文件。

我只想在任何给定时间激活一个文件。

我错过了什么?

我尝试将 <svelte:this> 组件移动到不同的位置。 所有数据都按预期传递。

REPL 这重现了问题。我的实际项目中的代码略有不同 - 但问题是一样的。 https://svelte.dev/repl/0f91294a827342e7b6b99d33576da909?version=3.38.3

原始示例(精巧的文档) https://svelte.dev/tutorial/svelte-self

<script>

    // App.svelte

    import Folder from './Folder.svelte';

    let root = [
        {
            type: 'folder',
            name: 'Animal GIFs',
            files: [
                {
                    type: 'folder',
                    name: 'Dogs',
                    files: [
                        { type: 'file', name: 'treadmill.gif' },
                        { type: 'file', name: 'rope-jumping.gif' }
                    ]
                },
                {
                    type: 'folder',
                    name: 'Goats',
                    files: [
                        { type: 'file', name: 'parkour.gif' },
                        { type: 'file', name: 'rampage.gif' }
                    ]
                },
                { type: 'file', name: 'cat-roomba.gif' },
                { type: 'file', name: 'duck-shuffle.gif' },
                { type: 'file', name: 'monkey-on-a-pig.gif' }
            ]
        },
        { type: 'file', name: 'TODO.md' },
        { type: 'file', name: 'Readme.md' }
    ];
</script>

<Folder name="Home" files={root} expanded/>





<script>

    // Folder.svelte

    import File from './File.svelte';

    export let expanded = false;
    export let name;
    export let files;
    
    let isActive = ""

    function toggle() {
        expanded = !expanded;
    }
    
    function activate(event) {
        console.log(event)
        isActive = event
    }
</script>

<span class:expanded on:click={toggle}>{name}</span>

{#if expanded}
    <ul>
        {#each files as file}
            <li> 
                {#if file.type === 'folder'}
                    <svelte:self {...file}/>
                {:else}
                <div on:click={activate(file.name)}>
                    <File {...file} {isActive} />
                </div>
                {/if}
            </li>
        {/each}
    </ul>
{/if}

<style>
    span {
        padding: 0 0 0 1.5em;
        background: url(tutorial/icons/folder.svg) 0 0.1em no-repeat;
        background-size: 1em 1em;
        font-weight: bold;
        cursor: pointer;
    }

    .expanded {
        background-image: url(tutorial/icons/folder-open.svg);
    }

    ul {
        padding: 0.2em 0 0 0.5em;
        margin: 0 0 0 0.5em;
        list-style: none;
        border-left: 1px solid #eee;
    }

    li {
        padding: 0.2em 0;
    }
</style>





<script>

    // File.svelte

    export let name;
    export let isActive = ""
    $: type = name.slice(name.lastIndexOf('.') + 1);
</script>

<span 
    class:active={isActive === name} 
    style="background-image: url(tutorial/icons/{type}.svg)">
    {name}
</span>

<style>
    span {
        padding: 0 0 0 1.5em;
        background: 0 0.1em no-repeat;
        background-size: 1em 1em;
    }
    .active {
        color: orange;
        font-weight: bold;
    }
</style>

您可以使用可写存储来保存 isActive,这样组件的每次迭代都不会获得它自己的私有 isActive 变量。

这是一个有效的 REPL https://svelte.dev/repl/7d4c7b8ee006484489d5141b04ae163c?version=3.38.3