javascript Svelte:使用类指令突出显示表行不起作用

vvppvyoh  于 2023-10-14  发布在  Java
关注(0)|答案(2)|浏览(88)

我最近开始研究Svelte,并希望创建一个名为SelectorTable的组件,它允许我通过单击它们来选择表的行。选定的行应该以不同的颜色突出显示。
我试着在class directive中使用构建。

<script lang="ts">
    type ObjectKey = keyof any; 
    export let data: any[] = [];
    export let key = 'id' as ObjectKey;
    let selected: Set<ObjectKey> = new Set<ObjectKey>();

    function toggle(id: ObjectKey) {
        if (selected.has(id)) {
            selected.delete(id);
        } else {
            selected.add(id)
        }
        console.log(selected)
        console.log(selected.has(id))
    }
</script>

<table>
    <thead>
        <tr>
            {#each Object.keys(data[0]) as heading}
            <th>{heading}</th>
            {/each}
        </tr>
    </thead>
    <tbody>
        {#each Object.values(data) as row}
            <tr class:tr-selected={selected.has(row[key])} on:click={() => {toggle(row[key])}}>
                {#each Object.values(row) as cell}
                <td>{cell}</td>
                {/each}
            </tr>
        {/each}
    </tbody>
</table>

<style>
    table, th, td {
        border: 1px solid;
        border-collapse: collapse;
        margin-bottom: 10px;
    }
    tr:hover {
        background-color: red;
        cursor: pointer;
    }

    .tr-selected { 
        background-color: greenyellow;
    }
</style>

on:click函数toggle可以正确地添加或删除选定的键。我的问题是,所选行的背景颜色没有改变,即使selected.has(row[key]) == true。下面是使用键1单击一行两次时的控制台输出。

> Set(1) {1} ------- SelectorTable.svelte:14 
> true ------------- SelectorTable.svelte:15
> Set(0) {size: 0} - SelectorTable.svelte:14
> false ------------ SelectorTable.svelte:15

首先将关键点添加到选定的集合中,然后再次将其删除。
那么,如果selected.has(row[key])的输出为true,为什么class指令不起作用,行的颜色也不改变?

kpbwa7wx

kpbwa7wx1#

React性是基于赋值的,所以如果你使用像Set这样的通过函数修改的东西,你可以在修改后添加一个虚拟赋值,以在使用集合的任何地方触发更新:

function toggle(id: ObjectKey) {
    if (selected.has(id)) {
        selected.delete(id);
    } else {
        selected.add(id)
    }

    selected = selected; // <--
}
nfg76nw0

nfg76nw02#

我找到了解决办法。不知道是否有更好的,但这一个工作。
在尝试了一段时间后,我意识到Svelte没有检查class指令中的selected.has(row[key]),因此没有重新呈现该行。然后,我尝试通过将selected设置到sveltes key逻辑块中,但它仍然不工作。
最后,我添加了一个新的布尔变量update,我在key块中引用它,每次调用函数toggle时,update都会被翻转。

<script lang="ts">
    type ObjectKey = keyof any; 
    export let data: any[] = [];
    export let key = 'id' as ObjectKey;
    let selected: Set<ObjectKey> = new Set<ObjectKey>();

    // Add update variable
    let update: boolean = false

    function toggle(id: ObjectKey) {
        // Flip updates value to indicate a change
        update = !update
        if (selected.has(id)) {
            selected.delete(id);
        } else {
            selected.add(id)
        }
    }
</script>

<table>
    <thead>
        <tr>
            {#each Object.keys(data[0]) as heading}
            <th>{heading}</th>
            {/each}
        </tr>
    </thead>
    <tbody>
        {#each Object.values(data) as row}
            <!-- Reference update to rerender the row when its value changes -->
            {#key update}
                <tr class:tr-selected={selected.has(row[key])} on:click={() => {toggle(row[key])}}>
                    {#each Object.values(row) as cell}
                    <td>{cell}</td>
                    {/each}
                </tr>
            {/key}
        {/each}
    </tbody>
</table>

<style>
    table, th, td {
        border: 1px solid;
        border-collapse: collapse;
        margin-bottom: 10px;
    }
    tr:hover {
        background-color: red;
        cursor: pointer;
    }

    .tr-selected { 
        background-color: greenyellow;
    }
</style>

如果我错了请纠正我。
我假设这种行为的原因是JS/TS通过引用传递对象和函数,如selectedtoggle,并通过值传递原始变量,如int或布尔值。
key状态的Sveltes文档
“当表达式的值更改时,键块将销毁并重新创建其内容。”
这可以解释为什么使用selected时该行没有重新呈现。因为它是通过引用传递的,引用也是基本类型,而且因为只有引用后面的值发生了变化,而不是引用本身,所以Svelte不能识别变化,因此不会重新呈现。
在类指令的文档中没有特别说明这种行为,但假设它是类似的是保存的。

相关问题