【问题标题】:Svelte component does not see prop update if in one slot, but does if in another slotSvelte 组件在一个插槽中不会看到 prop 更新,但如果在另一个插槽中则可以
【发布时间】:2021-10-07 05:41:52
【问题描述】:

在以下组件(称为“注释屏幕”)中,组件DocPicker 让用户设置变量selectedDoc,该变量又应该更新两个组件:FormSearchResultView

<script lang="ts">
  import type { AppScreen, QuestionGouv } from '../../types.js';
  import Screen from '../../Screen.svelte';
  import DocPicker from './DocPicker/DocPicker.svelte';
  import SearchResultView from '../../SearchResultView.svelte';
  import Form from './Form.svelte';

  export let screen: AppScreen;
  
  let selectedDoc: QuestionGouv;
  let isPickerOpen: boolean;
</script>

<Screen bind:screen>
  <svelte:fragment slot="sidebar">
    <DocPicker bind:picked={selectedDoc} bind:isOpen={isPickerOpen}/>
    {#if selectedDoc}
      <Form doc={selectedDoc}/>
    {/if}
  </svelte:fragment>
  <svelte:fragment slot="content">
    {#if selectedDoc}
      <SearchResultView doc={selectedDoc} on:close={() => {selectedDoc = undefined}}/>
    {/if}
  </svelte:fragment>
</Screen>

问题是Form 组件在selectedDoc 更改时没有更新。第一次selectedDocundefined 变为某个值时,组件Form 以正确的值出现,但如果后来selectedDoc 发生变化(因为用户使用了DocPicker),组件Form 保持与前一个价值。

SearchResultView 每次都会更新,就像一个魅力,所以我虽然问题来自 Form 组件,但如果我复制行 &lt;Form doc={selectedDoc}/&gt; 就在 SearchResultView 的位置旁边(即也就是说,在&lt;svelte:fragment slot="content"&gt;) 中,Form 的这个实例可以正常工作!同样,如果我将另一个SearchResultView 实例放在&lt;svelte:fragment slot="sidebar"&gt; 中,这个SearchResultView 实例不会更新。

所以它似乎与在哪里组件插入有关,即Screen组件的哪个插槽。但是Screen 组件非常琐碎,归结为:

<Sidebar>
  <div class="screen-sidebar">
    <slot name="sidebar"></slot>
  </div>
</Sidebar>
<slot name="content"></slot>

Sidebar 组件也很简单:

<div class="sidebar">
  <slot></slot>
</div>

【问题讨论】:

  • 您能否在REPL 中重现此行为。

标签: svelte svelte-3


【解决方案1】:

好的,知道了。事实证明,问题的原因不在我提出的问题中的代码 sn-ps 中。我在 Svelte 的 DocPicker 组件中做了一些你可能根本不应该做的事情。 Svelte 编译器没有抱怨,但显然很困惑,这导致了我在问题中描述的奇怪行为。

以下是问题的详细信息以及我是如何找到它的。

我试图提出一个最小的工作示例,以便我可以将它放在 Svelte REPL 中,当然问题不是重现。

所以我尝试了许多中间步骤,从我的问题情况到失败的最小工作示例,看看哪个精确的步骤会带回错误。将它带回来的是DocPicker 组件中的bind:isOpen={isPickerOpen} 属性绑定。所以问题很可能与这个组件有关。

我查看了这个DocPicker 组件的代码,并且isOpen 以一种奇怪的方式使用。我什至对此发表了评论警告:

export let isOpen: boolean = true;
$: isOpen = !Boolean(picked);
// XXX is it good practice to "force" a variable that is also reactively assigned?
function openPicker() {
  isOpen = true;
}

所以我想我现在在评论中得到了我对这个问题的答案:不,这可能不是一个好主意。或者也许不是这样。如果这总是一个坏主意,Svelte 编译器在看到这个时不会引发错误吗?

无论如何,我改变了 isOpen 的管理方式(不是通过响应式分配,只有命令式分配),现在它就像一个魅力。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-23
    • 1970-01-01
    • 2021-02-06
    • 2021-07-20
    • 1970-01-01
    • 2021-02-08
    • 1970-01-01
    相关资源
    最近更新 更多