Svelte中能否省略slot属性,直接将组件作为对应插槽使用?
问题:Svelte中能否省略slot属性,通过组件名自动对应插槽?
我正在构建一个Svelte应用,现有如下代码:
Main.svelte
<script> import TitleSlide from '../lib/slides/TitleSlide.svelte' </script> <TitleSlide> <span slot="title">To infinity and beyond</span> <span slot="caption">or story about toys</span> </TitleSlide>
TitleSlide.svelte
<section> <h1> <slot name="title"> <span class="missing">Unknown title</span> </slot> </h1> <p class="fragment"> <slot name="caption"></slot> </p> </section>
这段代码运行正常,之后我将Main.svelte改写为:
改写后的Main.svelte
<script> import TitleSlide from '../lib/slides/TitleSlide.svelte' import Title from '../lib/partial/Title.svelte' import Caption from '../lib/partial/Caption.svelte' </script> <TitleSlide> <Title slot="title">To infinity and beyond</Title> <Caption slot="caption">or story about toys</Caption> </TitleSlide>
Title.svelte 和 Caption.svelte
<slot> <span class="missing">Unknown title/caption</span> </slot>
但该写法略显繁琐,我希望使用更简化的语法,即省略slot属性,直接在TitleSlide中使用Title、Caption组件来对应指定插槽,请问该需求是否可以实现?
解答
可以实现,下面提供两种简洁可行的方案:
方案一:给子组件预设默认插槽绑定
修改Title.svelte和Caption.svelte,通过svelte:fragment预设默认对应的插槽名,这样使用时无需手动指定slot属性:
Title.svelte
<script> export let slot = 'title' </script> <svelte:fragment slot={slot}> <slot> <span class="missing">Unknown title</span> </slot> </svelte:fragment>
Caption.svelte
<script> export let slot = 'caption' </script> <svelte:fragment slot={slot}> <slot> <span class="missing">Unknown caption</span> </slot> </svelte:fragment>
之后在Main.svelte中就可以直接省略slot属性使用组件:
<script> import TitleSlide from '../lib/slides/TitleSlide.svelte' import Title from '../lib/partial/Title.svelte' import Caption from '../lib/partial/Caption.svelte' </script> <TitleSlide> <Title>To infinity and beyond</Title> <Caption>or story about toys</Caption> </TitleSlide>
方案二:在父组件中自动识别子组件分配插槽
修改TitleSlide.svelte,通过$$children遍历子组件,根据组件类型自动映射到对应插槽:
<script> import Title from '../lib/partial/Title.svelte' import Caption from '../lib/partial/Caption.svelte' let titleContent = null let captionContent = null $: { titleContent = null captionContent = null for (const child of $$children) { if (child.constructor === Title) titleContent = child.children if (child.constructor === Caption) captionContent = child.children } } </script> <section> <h1> {#if titleContent} <Title>{titleContent}</Title> {:else} <span class="missing">Unknown title</span> {/if} </h1> <p class="fragment"> {#if captionContent} <Caption>{captionContent}</Caption> {/if} </p> </section>
这种方式下Main.svelte同样可以省略slot属性直接使用组件,无需修改子组件代码。
两种方案中,方案一更符合Svelte的组件设计逻辑,代码更简洁易维护,推荐优先使用。
内容的提问来源于stack exchange,提问作者Anton Shevchuk
相关产品推荐
相关产品推荐

