【问题标题】:Restart or re-init component in Svelte在 Svelte 中重新启动或重新初始化组件
【发布时间】:2020-01-28 21:53:46
【问题描述】:

有没有一种简单的方法可以强制重启 Svelte 组件?

重启用例:

  • 清除 HTML 文件输入的文件列表(不能重置路径/值)
  • 使用 CSS 悬停时选择项目后导航栏下拉折叠

也许除了重启还有其他解决方案,这里还是用组件重启吧。

在适合上传用例的重启代码下方:

SomeApp.svelte

<script>
      ...
      import Upload from "./upload/Upload.svelte";

      export let uid;  // firebase uid from auth

      // restart the Upload component after the upload 
      // to clear the filename of the <input type="file" ..../>  
      // restart by making use of a dynamic (falsy) component
      let upload_component = Upload;
      let restart = false;

      $: if (restart) {
         // use a falsy to stop / destroy this component 
         upload_component = null;
         // use a timer to queue a restart after the component has stopped
         setTimeout(() => {
           console.log('Upload component restarts')
           upload_component = Upload
         }, 0);
         console.log('Upload component restart queued');
         restart = false;  
      };

      ...
</script>


<!-- dynamic upload to restart the component when finished-->
<svelte:component uid={uid} this={upload_component} bind:finished={restart}/>

上传.svelte

<script>
    import { onDestroy } from 'svelte';
    import { uploadCsv } from './upload.js'

    export let uid = null;
    export let finished;

    function uploadCsvCallback(result) {
      console.log(result);
      finished = true;
    };

    onDestroy(() => {
      console.log('Upload component destroyed');
    });
</script>

<style>
     .float-right {
          float: right;
      }
</style>

<!-- Select a CSV file to batch import a Firestore collection -->
<input
    type="file" name="files" class="float-right" accept=".csv" 
    on:change={uploadCsv(uid, uploadCsvCallback)}
/>

更新:
如果组件没有被渲染,组件就会被销毁。因此,您可以在切换组件周围的 if 块时停止和重新启动组件。

示例:
1. 将运行从 true 切换为 false 以销毁 Upload 组件
2. 将运行从 false 切换为 true 以重新启动 Upload 组件

{#if run}
  <Upload .....>
{/if}

您可以使用计时器来切换重启。

run = true:
function restartComponent() {
  restart = false;  // stop / destroy
  setTimeout(() => run = true, 0); // and queue a restart
}

【问题讨论】:

  • 如果自 2018 年 2 月以来没有任何变化,那么不,我们不能。 *.com/questions/48911519/recreate-a-component
  • 好的。在 3 之前,我对 Svelte 并不熟悉。而 3 是 majon 大修。我认为重启是可能的,但不是......
  • 它可以在没有动态组件的情况下完成。当组件在“活动”时未呈现时,它将被销毁。这意味着我们可以将上面的 放在 if 块中。如果我们切换 if 块,组件将重新启动。
  • 好主意!你介意用小演示来写官方答案吗?
  • 请把它移到明确的答案中!我担心有人可能会因为没有任何答案而错过从搜索中打开这个问题(所以他们不会知道你在问题部分提供了解决方案)

标签: svelte svelte-3 svelte-component


【解决方案1】:

是的,使用{#key} 块:

<script>
import YourComponent from "./YourComponent.svelte"

let unique = {}

function restart() {
  unique = {} // every {} is unique, {} === {} evaluates to false
}
</script>

{#key unique}
  <YourComponent />
{/key}

<button on:click={restart}>Restart</button>

REPL

{#key} 是在 Svelte v3.28 中引入的,在此之前您需要使用键控 {#each}with only one item

【讨论】: