Svelte和Sapper中的context="module"是如何工作的?

13
当我使用Sapper构建项目时,无论何时从服务器获取数据,preload函数都声明在context="module"的脚本内,如下所示。
<script context="module">
  export async function preload(page) {
    return await this.fetch(`https://reqres.in/api/users?page=1`)
    .then(res1 => {
      return res1.json()
    }).then(res2 => {
      return { 
        notices: res2.data,
      }
    })
  }
</script>

根据文档
A <script> tag with a context="module" attribute runs once when the module first evaluates, rather than for each component instance. 

但是“当模块首次评估”是什么意思?

它是否意味着当组件首次渲染时?那么在onMount生命周期方法中声明api fetch函数不就像下面的代码一样吗?

<script>
  onMount(async() => {
    const res = await fetch(`https://reqres.in/api/users?page=1`);
    const json = await res.json();
  })
</script>

据我所知,与每个组件实例调用一次的 onMount 不同,context="module" 的脚本仅执行一次。 - TurboHz
3个回答

27

考虑一个导出类的常规JavaScript模块:

// Component.js

console.log('evaluating module');

export class Component {
  constructor() {
    console.log('instantiating component');
  }
}

如果您将该模块导入您的应用程序中,那么该代码将立即运行:

import { Component } from './Component.js';

// "evaluating module" has already been logged. This will only happen once
// for the entire application, however many modules import Component.js

const component1 = new Component(); // logs "instantiating component"
const component2 = new Component(); // logs "instantiating component" again

现在我们可以用 Svelte 的术语来表述:

  • '评估模块'的代码就是发生在 <script context="module"> 中的内容
  • '实例化组件'的代码相当于在常规的 <script> 标签中发生的内容

1
是的,这是真的,虽然有一个小区别:使用context="module",调用是在创建组件之前执行的。
引用自官方文档:

它在组件创建之前运行

这对于像产品列表这样的情况非常有用...您不知道要显示哪些产品,因此您获取数据并为结果中的每个项目实例化一个产品组件。

1

当使用Sapper或SvelteKit(相当于React世界中的Next.js)时,SSR组件无法直接访问窗口对象,因此您需要等待组件“水化”或传统呈现。这意味着任何使用窗口的库,实际上是任何需要在浏览器中运行的内容,都必须通过onMount完成。

使用SSR时,例如SvelteKit等工具,onMount()不会在服务器上运行。因此,您的客户端依赖代码(例如本地存储访问)可以放置在onMount()中,这样它就不会引发服务器错误。

来自https://www.reddit.com/r/sveltejs/comments/p5p386/trying_to_understand_script_vs_onmount/


1
你没有回答context='module'的工作原理。 - manu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接