【问题标题】:Svelte application bug: converting string to boolean in the view failsSvelte 应用程序错误:在视图中将字符串转换为布尔值失败
【发布时间】:2020-11-10 19:30:49
【问题描述】:

在 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 所示。

我做错了什么?

【问题讨论】:

  • 为什么不直接绑定国家状态?它必须是 0 和 1 而不是 false 和 true 吗?
  • @Gh05d 我仍然需要将字符串 "0""1" 转换为字符串 01 的数字。所以我会有同样的问题。

标签: javascript svelte svelte-3


【解决方案1】:

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

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

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

    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

【讨论】:

    【解决方案2】:

    正如它在错误中所说,您只能将bind 指向标识符或成员表达式 - 即变量。

    这是因为bind 是一个双向的东西,如果你对它应用了Boolean(Number(()),当有人更改该输入时,svelte 不知道如何撤消这些功能以“保存”数据返回到它所绑定的变量中。

    如果您无法将状态变量更改为布尔值(更好的解决方案,正如其他答案所建议的那样),您需要手动执行此双向更新。删除bind,只使用checked={Boolean(Number(c.status))},并处理输入的change 事件以将真/假转换回“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 中的工作

    【讨论】:

    • 我需要更改countries 数组(数据必须保存在数据库中)我想我不能放弃bind
    • 我的意思是你可以改变它而无需绑定。 (用工作代码示例更新了答案)
    • 我用的是 Switch 而不是 Checkbox
    • 你还没有提到你是如何定义Switch的,所以我不能帮你。我只在我为您编写的演示代码中使用了一个复选框,以便它可以工作,您可以看到手动定义变量和输入框之间的绑定的示例。
    【解决方案3】:

    我认为问题在于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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-07
      • 1970-01-01
      • 2018-09-10
      • 2019-02-19
      • 2017-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多