【问题标题】:How to create dynamic tree structure in svelte?如何在 Svelte 中创建动态树结构?
【发布时间】:2021-07-30 09:09:40
【问题描述】:

我需要一个苗条的树视图,每个节点都有复选框。

我无法获得以下功能:如果我们检查父节点,那么它的所有(仅它的)子节点是否是文件夹文件,所有这些( child) 自动检查,其中任何一个都未选中,然后父级也应取消选中。我怎样才能做到这一点?

以下是我从here 遵循的代码。我尝试了一些东西,但没有运气。

App.svelte-

<script>
    import Folder from './Folder.svelte';

    let root = [
        {
            name: 'Important work stuff',
            files: [
                { name: 'quarterly-results.xlsx' }
            ]
        },
        {
            name: 'Animal GIFs',
            files: [
                {
                    name: 'Dogs',
                    files: [
                        { name: 'treadmill.gif' },
                        { name: 'rope-jumping.gif' }
                    ]
                },
                {
                    name: 'Goats',
                    files: [
                        { name: 'parkour.gif' },
                        { name: 'rampage.gif' }
                    ]
                },
                { name: 'cat-roomba.gif' },
                { name: 'duck-shuffle.gif' },
                { name: 'monkey-on-a-pig.gif' }
            ]
        },
        { name: 'TODO.md' }
    ];
</script>

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

File.svelte-

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

<span 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;
    }
</style>

Folder.svelte-

<script>
    import File from './File.svelte';

    export let expanded = false;
    export let name;
    export let files;
    let checkedState = true;

    function toggle() {
        expanded = !expanded;
    }
    
    function onCheckboxChanged(e){
        console.log("out: "+document.getElementById("cb1").checked)
    }
</script>

<input type="checkbox" on:change={onCheckboxChanged} id="cb1" bind:checked={checkedState}><span class:expanded on:click={toggle}>{name}</span>

{#if expanded}
    <ul>
        {#each files as file}
            <li>
                {#if file.files}
                    <svelte:self {...file}/>
                {:else}
                    <input type="checkbox" on:change={onCheckboxChanged} id="cb1" bind:checked={checkedState}><File {...file}/>
                {/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>

【问题讨论】:

    标签: html checkbox treeview svelte


    【解决方案1】:
    1. 删除文件组件旁边复选框中的绑定。当您单击文件的复选框并检查整个文件夹时,这将防止出现这种情况。相反,您只需在检查文件夹时将状态传递给子文件组件。所以修改代码如下:
    <!-- <input type="checkbox" bind:checked={checkedState}> -->
    <input type="checkbox" checked={checkedState}>
    
    1. 然后您需要将文件夹的选中状态传递给所有子文件夹组件(因此,当您检查文件夹时,内部的文件夹也会被检查)。您可以通过将checkedState 设为一个道具,而不仅仅是常规变量,然后在调用svelte:self 组件时传递此道具
    <script>
        // let checkedState = true;
        export let checkedState = true;
    </script>
    
    <!-- <svelte:self {...file}/> -->
    <svelte:self {...file} {checkedState} />
    
    1. 之后只剩下一个问题案例。当所有子组件都(未)选中时,父组件也应该(未)选中。我真的看不出用当前结构实现这个东西的可能性。我建议您在文件组件中移动复选框,然后在文件对象(在App.svelte)中创建字段checkedselected,以便您可以轻松管理任何子组件中的所有状态。从根文件夹组件中提取数据时,读取这些值也会更容易(例如,如果您需要将此数据发送到服务器)。添加道具后,您当然应该使用对象属性,而不是组件的状态。祝你好运!

    P.S:不要在组件中使用静态 ID,在每个循环中更是如此。这将使您的输出 html 无效。

    【讨论】:

    • 感谢您的回答。您能帮我获取与复选框对应的项目详细信息吗?
    猜你喜欢
    • 2017-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多