Svelte中更新store后如何重新触发if-else语句?
问题描述
我正在构建的组件中使用字符串列表作为状态(favourites):
<script lang="ts"> let favorites: string[] = []; let listingsList: any = []; function favourite(listingID: string) { // do some stuff favourites.push(listingID) } </script>
它用于跟踪组件的id,根据id是否在列表中显示不同的按钮:
{#each listingsList as listing} {#if favorites?.includes(listing.id)} <button class="btn btn-sm btn-secondary" on:click={() => favourite(listing?.id)}>Saved</button> {:else} <button class="btn btn-sm btn-primary" on:click={() => favourite(listing?.id)}>Save it!</button> {/if} {/each}
问题:点击按钮后,控制台显示列表已更新,但按钮并未切换。刷新页面后,按钮才会正常显示预期状态。这是预期行为吗?有没有办法在列表更新后重新触发if语句,让按钮立即切换?
解决方案
这不是预期行为,核心原因是Svelte的响应式更新逻辑:
- Svelte通过变量的重新赋值来检测状态变化,原地修改数组(比如
push、splice)不会改变变量的引用,因此Svelte无法感知到数组内容的变化,也就不会触发视图更新。
你可以通过以下两种方式解决:
方式1:重新赋值数组
修改favourite函数,通过创建新数组的方式触发响应式更新:
function favourite(listingID: string) { // 方法A:push后重新赋值 favorites.push(listingID); favorites = [...favorites]; // 方法B:直接生成新数组(更简洁) // favorites = [...favorites, listingID]; }
方式2:使用Svelte Writable Store
如果需要跨组件共享收藏状态,或者更规范的响应式管理,推荐使用Svelte的writable store:
import { writable } from 'svelte/store'; // 定义store const favorites = writable<string[]>([]); function favourite(listingID: string) { // 更新store,自动触发响应式 favorites.update(current => [...current, listingID]); }
在模板中使用时,需要给store变量加上$前缀:
{#each listingsList as listing} {#if $favorites?.includes(listing.id)} <button class="btn btn-sm btn-secondary" on:click={() => favourite(listing?.id)}>Saved</button> {:else} <button class="btn btn-sm btn-primary" on:click={() => favourite(listing?.id)}>Save it!</button> {/if} {/each}
额外注意
你的代码中存在拼写不一致:变量定义是favorites(美式),但函数内写的是favourites(英式),需要统一拼写,否则会导致实际状态未更新的问题。
内容的提问来源于stack exchange,提问作者Pablo L
相关产品推荐
相关产品推荐

