在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不知道如何撤消这些函数,将数据"保存"回它绑定的变量中。
如果您不能将状态变量更改为布尔值(正如其他答案所建议的那样,这是更好的解决方案(,则需要手动进行双向更新。删除bind
,只拥有checked={Boolean(Number(c.status))}
,并处理输入的change
事件,将其从true/false转换回"true";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)}/>
看到它在这个复制中工作
我认为问题在于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
参数绑定到countries数组的变量。请注意,为了使其正常工作,您需要将状态值更改为true
或false
。否则它仍然有效,但初始值将始终为true
。
如果您只想将值传递给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