You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Svelte视图不随变量变更实时更新:点击多次才随机生效的原因

问题:Svelte中点击按钮切换行展开状态时,视图更新异常

代码意图是当行的唯一ID存在于expandedRows数组中时,显示对应的展开行,但实际点击按钮时,Svelte需要多次点击才会随机更新视图。

原代码

<script>
    import { onMount } from "svelte";

    let rows = [
        {"name": "Alex", "id": "0"},
        {"name": "Steve", "id": "1"},
        {"name": "Mike", "id": "2"},
    ]; 

    let expandedRows = [];
    
    function toggleExpandRows(row_id_to_toggle) {
        console.log("Row to toggle:", row_id_to_toggle)
        console.log(expandedRows);
        if (expandedRows.includes(row_id_to_toggle)) {
            console.log(expandedRows, "includes", row_id_to_toggle)
            expandedRows = expandedRows.filter(expanded_row_id => expanded_row_id !== row_id_to_toggle)
        } else {
            expandedRows.push(row_id_to_toggle);
        }
    }
</script>

<div class="overflow-x-auto w-full">
    <table class="table table-compact w-full">
        <thead>
            <tr>
                <th></th>
                <th>Name</th>
            </tr>
        </thead>
        <tbody>
            {#each rows as row (row.id)}
                <tr>
                    <td>
                        <button class="btn btn-xs" on:click={()=>toggleExpandRows(row.id)}>+/-</button>
                    </td>
                    <td class="min-w-[3rem] ">{row.name}</td>
                </tr>
                row.id: {JSON.stringify(row.id)}
                {#if expandedRows.includes(row.id)}
                    <tr>
                        <td colspan="2">-</td>
                    </tr>
                {/if}
            {/each}
        </tbody>
    </table>
    Expanded: {JSON.stringify(expandedRows)}
</div>

原因分析

Svelte的响应式更新依赖于变量赋值触发。当前代码存在两种不同的数组修改逻辑:

  • 关闭展开行时,filter方法返回新数组并赋值给expandedRows,这会触发Svelte的响应式检测,视图正常更新;
  • 打开展开行时,push方法直接修改原数组的内容,但没有改变expandedRows的引用,Svelte无法感知到数组内部的变化,因此不会更新视图。

这种差异导致点击按钮时,只有关闭操作能立即生效,打开操作的变化会被延迟,直到后续触发关闭操作(赋值新数组)时才会一并渲染,看起来像是“多次点击后随机更新”。

解决方案

将打开行时的push操作改为创建新数组并赋值,确保Svelte能检测到变量变化:

// 替换原else块中的代码
expandedRows = [...expandedRows, row_id_to_toggle];

修改后的完整toggleExpandRows函数:

function toggleExpandRows(row_id_to_toggle) {
    console.log("Row to toggle:", row_id_to_toggle)
    console.log(expandedRows);
    if (expandedRows.includes(row_id_to_toggle)) {
        console.log(expandedRows, "includes", row_id_to_toggle)
        expandedRows = expandedRows.filter(expanded_row_id => expanded_row_id !== row_id_to_toggle)
    } else {
        expandedRows = [...expandedRows, row_id_to_toggle];
    }
}

这样每次切换操作都会触发赋值,Svelte能及时响应expandedRows的变化,视图会立即更新。

内容的提问来源于stack exchange,提问作者tonysepia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 20:55:59