1

假设我有一堆数据文档,它们是 S3 中的 JSON 文档,每年一个。我通过 dir 结构在 Sapper 中定义了一条路线:

├── routes
│   ├── _error.svelte
│   ├── _layout.svelte
│   ├── about.svelte
│   ├── data
│   │   ├── [year].svelte

我的代码script块中的代码:

  let yearData;
  onMount(async () => {
    const f = await fetch(yearDataUrl(year), {
      headers: { 'Access-Control-Allow-Origin': '*' }
    });
    const jsonResults = await f.json();
    yearData = jsonResults;
  });

每个数据集在 S3 中为[s3 url]/[year here].json. 导航栏中有一组链接显示每个数据集。我可以onMount很好地加载数据,但随后单击导航栏链接不会加载新数据。所以onMount很可能是错误的选择。

我应该如何构建这个?另外值得注意的是,我想将这些页面呈现为静态文件(数据很少更改,尤其是前几年)。

4

1 回答 1

5

有两种选择。第一个也是最惯用的——在你的情况下也是正确的,因为听起来你想使用服务器端渲染——是使用preload

<script context="module">
  export async function preload(page) {
    const f = await this.fetch(yearDataUrl(page.params.year), {
      headers: { 'Access-Control-Allow-Origin': '*' }
    });

    return {
      yearData: await f.json()
    };
  }
</script>

<script>
  export let yearData;
</script>

<!-- use yearData here -->

preload 函数将在组件创建之前运行,并为其提供yearDataprop。每当page.params更改时,preload将再次运行,设置新的道具。

因为这在服务器和客户端上都有效(因此使用this.fetch而不是fetch在两种环境中都有效),您将获得服务器呈现的页面,而不是在运行时立即闪烁到页面中的加载消息onMount

为了完整起见,第二个选项是使用页面存储

<script>
  import { stores } from '@sapper/app';

  const { page } = stores();

  let yearData;

  $: if (process.browser) {
      fetch(yearDataUrl($page.params.year))
        .then(f => f.json())
        .then(data => {
          yearData = data;
        });
  }
</script>

在这种情况下yearData ,不会被服务器渲染。(要完整,您还需要处理竞争条件和错误,这不是问题preload。)

于 2019-08-24T19:35:11.453 回答