Svelte - 绑定子组件的 属性

Svelte - bind on child component's property

我有一个应用程序可以简单地隐藏内容 Hidden.svelte:

<script>
    export let shown = false;
</script>

<svelte:options accessors={true}/>

{#if shown}
    <slot/>
{/if}

父级一切正常 App.svelte:

<script>
    import Hidden from 'Hidden';

    let child;
</script>

<Hidden bind:this={child}>
    Content
</Hidden>

<button on:click={() => child.shown = true}>Show</button>

但是,虽然我可以做到这一点on:click={child.shown = true},但我不能做到这一点:

{#if child.shown}
    External message!
{/if}

显然,我也做不到:

<div class:shown={child.shown}>Child component is shown</div>

我想,这都是因为它在安装之前呈现,但我所有尝试玩 onMount$: 都失败了

能以某种方式实现吗?感谢

编辑

抱歉,各位,我已经尝试制作尽可能简单的示例,并制作了一个根本无法反映我最初问题的示例,但是,从技术上讲,我得到了正确的答案

所以,问题是,父级 App.svelte 没有反映直接在 Hidden.svelte

中进行的 child.shown 更改

@ThomasHennes 建议使用商店来解决这个问题,但是,如果我做对了,这对单个应用程序实例来说是个好方法,所以,对于那些感兴趣的人,我最终得到了定期事件:

https://svelte.dev/repl/f467fe36446444f09a2a7633b1faa6a1?version=3.20.1

编辑 2

实际问题已在接受的答案中解决

您需要做的就是测试 childchild.shown:

{#if child && child.shown}
    External message!
{/if}

<div class:shown={!child || !child.shown}>Child component is shown</div>

https://svelte.dev/repl/10f1e41e4fc3465d81bba5efcff84c4a?version=3.20.1

您还可以使用反应值来管理组合条件:

$: childShown = child && child.shown

然后使用 childShown!childShown 有条件地显示内容。

我想你可能忽略了一个更直接的可能性:bind:property.

虽然 bind:this 对于抓取 DOM 元素非常有用,但我倾向于认为它是组件的最后解决方案。

如果您设法让 Svelte 知道需要跟踪什么,那么生成的代码很可能会比您自己使用事件或其他任何东西更高效。部分是因为它将使用已经存在于您的应用程序中的 Svelte 运行时代码,部分是因为 Svelte 会生成经过认真优化的更改跟踪代码,这将很难在保持人性化的同时编写所有代码。部分原因是您的更改跟踪目标会更窄。

此外,您将获得更简洁的代码。更多由机器处理的样板意味着更多的人可以用于实际逻辑。

所以...如果您对道具的变化值感兴趣,可以绑定到道具。这是我的做法。

Hidden.svelte

<script>
  export let shown = false // <= you can bind to this!

  export const show = () => { shown = !shown } // <= you can bind to this, too!
</script>

<button on:click={show}>Child's button</button>

{#if shown}
  <slot/>
{/if}

App.svelte

<script>
  import Hidden from './Hidden.svelte'

  let shown
  let show
</script>

<button on:click={show}>Parent's button</button>

<Hidden bind:shown bind:show>
  <div>Hidden content</div>
</Hidden>

{#if shown}
  <div>Hidden child is shown!</div>
{/if}

REPL