Svelte组件在一个槽中看不到prop更新,但在另一个槽中看到



在下面的组件(称为"注释屏幕")中,组件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>

问题是selectedDoc发生变化时,Form组件不会更新。当selectedDoc第一次从undefined移到某个值时,组件Form以正确的值出现,但如果后来selectedDoc发生变化(因为用户使用了DocPicker),组件Form保持之前的值。

SearchResultView每次更新虽然,像一个魅力,所以我认为问题来自Form组件,但如果我复制行<Form doc={selectedDoc}/>旁边的SearchResultView是(也就是说,在<svelte:fragment slot="content">),Form的这个实例工作没有问题!同样,如果我把SearchResultView的另一个实例放在<svelte:fragment slot="sidebar">中,这个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>

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

以下是问题的细节以及我是如何发现它的。

我试着想出一个最小的工作例子,这样我就可以把它放在一个简洁的REPL中,当然,问题没有重现。

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

我看了看这个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的管理方式(不是通过响应式分配,只有命令式分配),现在它像魅力一样工作。

相关内容

  • 没有找到相关文章

最新更新