Svelte从API获取数据后UI未渲染问题求助
问题分析
你的核心问题出在模板中的{#await}只会执行一次,而getData函数虽然依赖data,但它不是响应式的——当onMount中更新data后,不会重新触发getData执行,导致UI一直使用初始的空数组结果。另外,getData标记为async完全没必要,函数内部没有异步操作,反而让{#await}误以为它是异步任务,初始执行后就不再关注后续的data变化。
修复方案
方案1:直接在模板中处理数据(最简洁)
去掉getData函数,直接在模板里根据show_all和data的值渲染,利用Svelte的响应式自动更新UI:
<script lang="ts"> import Card from "../../components/Card.svelte"; import { onMount } from "svelte"; let show_all = false; let data: Array<{id: number, image_url: string, description: string, link: string, title: string}> = []; let loading = true; let error: Error | null = null; onMount(async () => { try { const response = await fetch("http://localhost:4000/entries"); data = await response.json(); } catch(err) { error = err as Error; } finally { loading = false; } }); </script> {#if loading} <p>...waiting</p> {:else if error} <p style="color: red">{error.message}</p> {:else} {#each (show_all ? data : data.slice(0, 12)) as item (item.id)} <Card image_url={item.image_url} description={item.description} link={item.link} title={item.title} /> {/each} {/if}
方案2:使用响应式派生值封装逻辑
如果想把数据筛选逻辑封装起来,用Svelte的响应式声明($:)定义filteredData,这样当data或show_all变化时,它会自动重新计算:
<script lang="ts"> import Card from "../../components/Card.svelte"; import { onMount } from "svelte"; let show_all = false; let data: Array<{id: number, image_url: string, description: string, link: string, title: string}> = []; let loading = true; let error: Error | null = null; onMount(async () => { try { const response = await fetch("http://localhost:4000/entries"); data = await response.json(); } catch(err) { error = err as Error; } finally { loading = false; } }); // 响应式派生值,依赖data和show_all变化自动更新 $: filteredData = show_all ? data : data.slice(0, 12); </script> {#if loading} <p>...waiting</p> {:else if error} <p style="color: red">{error.message}</p> {:else} {#each filteredData as item (item.id)} <Card image_url={item.image_url} description={item.description} link={item.link} title={item.title} /> {/each} {/if}
关键知识点
- Svelte的响应式基于变量赋值,当
data被重新赋值后,所有依赖它的模板或响应式声明都会自动更新。 {#await}适合处理真正的异步Promise(比如直接的fetch请求),不适合同步响应式逻辑,因为它只会执行一次Promise解析过程。- 响应式声明(
$:)是Svelte处理派生数据的核心方式,依赖变量变化时,声明块会自动重新执行。
内容的提问来源于stack exchange,提问作者Data Mastery
相关产品推荐
相关产品推荐

