Svelte 应用程序不会在浏览器中呈现我的数据

bul*_*r17 4 javascript rest json svelte sveltekit

我对 Svelte 还很陌生,我正在尝试在浏览器中渲染我的数据对象。我不确定发生了什么,因为后端似乎没问题,并且我能够在控制台中打印数据对象。

我有一个后端 Flask api,它读取以下 url

https://api.le-systeme-solaire.net/rest/bodies/

就这样并且工作正常。如果你查一下,你可以看到 json 是什么样子的

这是我的 index.svelte 文件的上半部分:

<script>

let data = []

async function initFetchSolarSystemData() {
 let response = await fetch("http://127.0.0.1:5000/solar-system/gravity");
 data = await response.json();

console.log("data", data)
console.log(["id", data.bodies[0].id])
console.log(["gravity", data.bodies[0].gravity])
console.log(["bodies", data.bodies.length])
}

initFetchSolarSystemData()

</script>
Run Code Online (Sandbox Code Playgroud)

因此,当它运行时,我可以在控制台中看到如下值:

['id', 'lune']
['gravity', 1.62]
'bodies', 287]
Run Code Online (Sandbox Code Playgroud)

所以这似乎也运作良好。这是文件的底部部分,我认为错误源于此:

<section>

    {#if data.length}
        {#each data.bodies as item}

            <div class="gravity">
              <h1 id="item">
                {item.gravity}
              </h1>
            </div>

        {/each}
    {/if}

</section>
Run Code Online (Sandbox Code Playgroud)

当我运行脚本时,控制台中没有出现任何错误。没有任何渲染。如果我替换这一行:

 {#if data.length}
Run Code Online (Sandbox Code Playgroud)

{#if data.bodies.length}
Run Code Online (Sandbox Code Playgroud)

我得到:

Cannot read properties of undefined (reading 'length')
Run Code Online (Sandbox Code Playgroud)

我对此感到困惑,因为这些值是在文件的前面读取的。

我想我在这里遗漏了一些东西,任何帮助将不胜感激。

Prz*_*law 5

tl;dr:有一个Array/Object混淆;将 更改{#if data.length}{#if data.bodies?.length}.

\n

问题

\n
\n

当我运行脚本时,控制台中没有出现任何错误。没有任何渲染。

\n
\n

{#if data.length}gets 第一次求值时,data变量仍然保存初始的空数组,因此 the#if得到一个 falsy 0

\n

这也是为什么用 替换 会{#if data.length}导致{#if data.bodies.length}错误 \xe2\x80\x94 data.bodiesis undefined,因此length查找失败。

\n

稍后,当fetch完成时,data被分配一个Object,因此{#if data.length}这次得到一个 falsy undefined

\n

因此,在fetch\xe2\x80\x94 之前和之后都不会呈现任何内容。

\n
\n

解决方案

\n

Thedata应该是 anObject而不是 an Array#if因此应该检查 the 的长度data.bodies而不是其data本身。
\n然后,要么:

\n

#1:等待获取

\n

Svelte 块包裹<section>\xe2\x80\xa6</section>内容,如下所示:await

\n
  {#await initFetchSolarSystemData()}\n    <p>Loading\xe2\x80\xa6</p>\n  {:then data}\n    \xe2\x80\xa6\n  {:catch error}\n    <p>Uh oh, an error.</p>\n  {/await}\n
Run Code Online (Sandbox Code Playgroud)\n

另外,为了方便它:

\n
    \n
  1. 将函数修改initFetchSolarSystemData()为.returndata
  2. \n
  3. initFetchSolarSystemData()从您所在的位置删除呼叫<script>\xe2\x80\xa6</script>
  4. \n
\n

演示: https://codesandbox.io/embed/lively-river-dni3l6 ?fontsize=14&hidenavigation=1&theme=dark

\n
\n

#2:获取false第一个,然后让 Svelte 触发更新

\n

(非常感谢@StephaneVanraes指出了这一点)

\n

或者,当在 之前运行时,#if和可能会先默默地“失败” ,并且一旦完成并将接收到的对象分配给 , Svelte 随后会触发更新#eachfetchfetchdata

\n

例如,可以通过从一开始就设置data一个属性来完成此操作:bodies

\n
let data = { bodies: [] }\n{#if data.bodies.length}\n
Run Code Online (Sandbox Code Playgroud)\n

或者使用可选的链接运算符

\n
{#if data.bodies?.length}\n
Run Code Online (Sandbox Code Playgroud)\n

演示https://codesandbox.io/embed/hungry-lederberg-78pr3g ?fontsize=14&hidenavigation=1&theme=dark

\n
\n

我希望这回答了你的问题。=) \n另请参阅@StephaneVanraes
的答案。

\n

  • 使用“#await”是一个非常好的建议,但是您的问题描述是错误的,如果 OP 分配了一个实际的“Array”而不是“Object”,那么它们的代码将按预期工作,因为 Svelte 会发现数组发生了变化,无论它是异步的。 (2认同)