我应该在父组件中创建这些函数并将它们传递给子组件以提高性能吗?或者 Svelte 能够 "hoist" 他们吗?

Shall I create these functions in parent component and pass them to child for a performance improvement? Or is Svelte able to "hoist" them?

假设我有一个组件:

<script lang="ts">
  const players: Player[] = getPlayersFromSomewhere()
</script>

{#each players || [] as player}
  <Player {player} />
{/each}
<script lang="ts">
  export let player: Player;
  
    async function doSomethingWithPlayer() {
    // many lines of code here...
    }

    async function doSomethingElse() {
    // many lines of code here...
    }

    async function doSomethingElseAgain() {
    // many lines of code here...
    }

  // ... many functions here
</script>

player is used here with many buttons like:

<button on:click={doSomethingWithPlayer}>...</button>
<button on:click={doSomethingElse}>...</button>
<button on:click={doSomethingElseAgain}>...</button>

问题是

Svelte 是为每位玩家重新创建 Player.svelte 中的功能,还是只为每位玩家使用一次?

我可以在 Page.svelte 中创建函数并将它们传递给 Player.svelte 吗?还是 Svelte 能够“提升”它们?

无论初始化组件多少次,您都只能使用模块上下文 运行 编码一次。我建议你看看 answer from Rich Harris and the official module context tutorial.

Svelte 将自动提升不依赖于本地组件状态的函数。来自 the docs:

Don't worry about the fact that we're redeclaring the foo function for every component instance — Svelte will hoist any functions that don't depend on local state out of the component definition.

您可以在 Svelte REPL 中看到此行为。考虑以下组件。

<script>
    let name = 'world';
    
    function changeName() {
        name = name + 1;
    }
    
    function log() {
        console.log("I'm independent")
    }
</script>

<h1>Hello {name}!</h1>

<button on:click={changeName}>
    Change
</button>

<button on:click={log}>
    Log
</button>

changeName依赖组件状态,而log不依赖,所以被吊出组件。您在编译后的 JS 中看到以下内容:只有一个 log 函数,但每个实例都会创建 changeName

function log() {
    console.log("I'm independent");
}

function instance($$self, $$props, $$invalidate) {
    let name = 'world';

    function changeName() {
        $$invalidate(0, name = name + 1);
    }

    return [name, changeName];
}

class App extends SvelteComponent {
    constructor(options) {
        super();
        init(this, options, instance, create_fragment, safe_not_equal, {});
    }
}