Svelte 应用程序错误:在视图中将字符串转换为布尔值失败

Svelte application bug: converting string to boolean in the view fails

在 Svelte 应用中,我有这样一组国家:

let countries = [
    {
        name:"Alegeria",
        status: "1"
    },
    {
        name:"Bulgaria",
        status :"0"
    }
]

注意 status 属性 是一个字符串。我以这种方式迭代数组:

{#if countries.length > 0}
<table class="table">
    <thead>
        <tr>
            <th>Country</th>
            <th class="text-right">Status</th>
        </tr>
    </thead>
    <tbody>
        {#each countries as c}  
        <tr>
            <td>{c.name}</td>
            <td class="text-right"><Switch bind:checked={Boolean(Number(c.status))} /></td>
        </tr>
    {/each}
    </tbody>
</table>
{:else}
<p class="alert alert-danger">No countries found</p>
{/if}

如您所见,我尝试使用 Boolean(Number(c.status)).

status 属性 的值转换为布尔值

我得到的不是所需的转换,而是错误:Can only bind to an identifier (e.g. foo) or a member expression,如 REPL 所示。

我做错了什么?

如错误中所述,您只能 bind 标识符或成员表达式 - 即变量。

这是因为 bind 是双向的,如果您已将 Boolean(Number(()) 应用到它,当有人更改该输入时,svelte 不知道如何撤消这些'save' 将数据返回到它所绑定的变量中。

如果您不能将状态变量更改为布尔值(更好的解决方案,如其他答案所建议的那样),您需要手动执行此双向更新。删除 bind,只有 checked={Boolean(Number(c.status))},并处理输入的 change 事件以从 true/false 转换回“1”或“0”,并将其保存到状态.

使用:

function handleClick(country) {
    countries.find(c => c.name == country.name).status = (country.status == "1") ? "0" :"1"
}

<Switch checked={Boolean(Number(c.status))} on:change={() => handleClick(c)}/>

查看它在 this repl

中的工作情况

我认为问题在于 Boolean() 函数创建了一个您无法绑定的新对象,因为它再也不会被引用。您可以使用以下代码直接绑定到 countries 中的值数组:

{#each countries as c, index}   
    <tr>
        <td>{c.name}</td>
        <td class="text-right"><Switch bind:checked={countries[index].status} /></td>
    </tr>
{/each}

改变的是您现在使用 #each 循环的 index 参数绑定到国家数组的变量。请注意,为了使其正常工作,您需要将状态值更改为 truefalse。否则它仍然有效,但初始值将始终为 true.

如果您只想将值传递给 Switch 组件,只需像这样删除 bind:

<td class="text-right"><Switch checked={Boolean(Number(c.status))} /></td>

如果您想通过切换组件更新国家/地区模型,我建议转发点击事件并使用简单的点击处理方法,如下所示:

    function onClick(event, country) {
        countries = countries.map(c => {
            if (c.name ===  country.name) {
                c.status = event.target.checked ? '1' : '0';
            }
            return c;
        })
    }

    ...

    <td class="text-right"><Switch checked={c.status === '1'} on:click={(e) => onClick(e, c)}/></td>

REPL 上的完整代码:https://svelte.dev/repl/013286229d3847c1895c4977aee234af?version=3.9.1