如何触发/强制更新Svelte组件

时间:2019-07-04 15:44:26

标签: svelte

我正在努力使我的头变得苗条的3反应性...

  1. 我想在单击按钮时强制刷新UI。我正在使用自定义组件AsyncFetcher,该组件接受HTTP发布数据,并为其插槽返回data对象(http发布结果)。

  2. 我想具有禁用功能。因此,当单击“禁用”按钮时,将调用http api,然后刷新数据视图。

<script>
    export let id

    function onDisable() {
        fetch('disable-api-url', {id: id})
        // Then ??
        // What to do after the fetch call, to refresh the view
    }
</script>

<AsyncFetcher postParam={id} let:data>
    {data.name}

    <button on:click={??}>Refresh</button>
    <button on:click={onDisable}>Disable Item</button>
</AsyncFetcher>

我尝试做on:click={() => id=id}来欺骗它以刷新为无效。如果id应该是对象而不是字符串id={...id}可以工作,那么不幸的是,这里不是这种情况。

实现此目标的正确方法是什么?

3 个答案:

答案 0 :(得分:2)

使用组件来管理提取非常不常规。通常,您可以在onMount内部或事件处理程序中获取数据:

<script>
  import { onMount } from 'svelte';

  let initialData;
  let otherData;

  onMount(async () => {
    const res = await fetch('some-url');
    initialData = await res.json();
  });

  async function update() {
    const res = await fetch('some-other-url');
    otherData = await res.json();
  }
</script>

{#if initialData}
  <p>the data is {initialData.something}</p>
{/if}

<button on:click={update}>update</button>

答案 1 :(得分:1)

就我而言,svelte 没有刷新输出,
因为我通过以 100% cpu 运行基准来阻止 javascript 事件循环

在这种情况下,诀窍是使用 await sleep(10)

手动解锁事件循环
<script>
  function sleep(millisec = 0) {
    return new Promise((resolve, reject) => {
      setTimeout(_ => resolve(), millisec);
    });
  };
  let result = '';
  async function runBenchmark() {
    for (let step = 0; step < 10; step++) {

      // this needs 100% cpu, so no time for svelte render
      cpuburn(); result += `${step}: 1.234 sec\n`;

      // unblock the JS event loop, so svelte can render
      await sleep(10);
    }
  }
</script>

<pre>{result}</pre>

here 是一个 repl(但目前它在 repl 运行时触发了一个错误)

用同步函数调用解决这个问题可能是不可能的
(类似于 $$svelte.forceTickSync()

答案 2 :(得分:0)

尽管Rich Harris提供了一个完全可服务的答案,但这是一种强制Svelte更新组件以反映其数据(also posted here外部更改的解决方案。

>

main.js ;在线示例中的香草,没有特殊更改:

import App from './App.svelte';

var app = new App({
    target: document.body
});

export default app;

index.html ;注意window.neek = {...}

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Svelte app</title>
    <script>
        window.neek = { nick: true, camp: { bell: "Neek" }, counter: 0 };
    </script>
    <script defer src='/build/bundle.js'></script>
</head>
<body>
</body>
</html>

App.svelte ;请注意$: notneek = window.neekwindow.neek.update = ...

<script>
    let name = 'world';
    $: notneek = window.neek;

    function handleClick() {
        notneek.counter += 1;
    }

    window.neek.update = function () {
        notneek = notneek;
    }
</script>

<h1>Hello { notneek.camp.bell }!</h1>

<button on:click={handleClick}>
    Clicked {notneek.counter} {notneek.counter === 1 ? 'time' : 'times'}
</button>

由于update函数在App.svelte的范围内,因此可以在通过window.neek.update()调用时强制重新渲染。此设置将window.neek.counter用于按钮使用的内部数据(通过notneek.counter),并允许在组件外部更新深层属性(例如neek.camp.bell = "ish"),并在{{ 1}}。

在控制台中,键入neek.update()并注意window.neek.camp.bell = "Bill"尚未更新。现在,在控制台中输入Hello Neek!,UI将会更新为window.neek.update()

最重要的是,您可以在Hello Bill!函数中根据需要进行任意细化,这样只有要同步的片段才可以。