如何在svelte 3中强制渲染?

时间:2019-10-15 22:46:12

标签: svelte

我有一个带有输入字段的表单。当我键入(键入)Enter键时,必须清除这些字段之一。我知道我可以将此字段作为受控字段进行处理(意味着监听keyup并维护该字段的副本),或者使用双向绑定,但是在我的用例中,我不能做到后者,我宁愿不做前者。因此,我的问题是,如何强制渲染Svelte组件?

通常情况下,表单显示为<Component field="value" />,用户修改字段并单击Enter键,我希望app.set(field, value)将字段重置为value ,即使在斯维尔特(Svelte)眼中,field属性也没有改变。有可能吗?

我尝试失败的方法是更新Svelte组件的内部属性 ,希望当app.set(field, value)时,Svelte会看到field的两个不同值属性并更新组件。但这似乎不起作用:

<script>

  const watchForEnter = ev => {
    if (ev.keyCode === 13) {
      ev.preventDefault();
      const formData = new FormData(ev.target.closest("form"));
      const tag = formData.get("tag");
      dispatch({ [ADDED_TAG]: tag });
    }
  };

  const updateCurrentTag = ev => {
    currentTag = new FormData(ev.target.closest("form")).get("tag");
    console.log(`currentTag!`, currentTag)
  }

</script>

        <form>
            <fieldset class="form-group">
              <input
                name="tag"
                class="form-control"
                type="text"
                placeholder="Enter tags"
                on:input={updateCurrentTag}
                value={currentTag}
                on:keyup={watchForEnter} />
            </fieldset>
        </form>

2 个答案:

答案 0 :(得分:1)

我不能完全理解您提供的示例中的所有内容,但是对于您的问题的一般回答是,在Svelte中,您应避免出现需要自己触发更新的情况。

在大多数情况下,可以使您的组件更具声明性,并更好地利用反应性(尤其是反应性语句),使Svelte可以在需要时进行呈现。

但是,在不可能的情况下,作为一种解决方法,您可以滥用{#each ...}块的键来强制Svelte重新创建通常会被重用的组件。

例如:

<script>
  export let allItems
  export let currentCategory

  $: items = allItems.filter(x => x.category === currentCategory)
</script>

{#each [items] as todos (currentCategory)}
  <Todos {todos} />
{/each}

有关更多详细信息,请参见this other answer(复制了上面的示例)。

另请参阅this REPL,其中显示了如何将这种hack实施到可重用的组件中,以使使用者的语法更简洁。

为了完整起见,还出现了this issue,并要求提供此功能。

答案 1 :(得分:0)

我相信我已经找到了一种优雅的解决方案,可以解决在组件数据超出其范围之外时强制组件进行更新的问题。

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!函数中根据需要进行任意细化,这样只有要同步的片段才可以。