如何继承带有苗条组件的插槽?

Posted

技术标签:

【中文标题】如何继承带有苗条组件的插槽?【英文标题】:How to inherit slots with svelte components? 【发布时间】:2022-01-23 19:00:11 【问题描述】:

有一个组件<Bar> 继承自组件<Foo>

<Foo> 组件定义了一个名为 content 的插槽,其中包含备用内容。 <Bar> 组件还定义了一个名为 content 的插槽,具有不同的后备内容。

<!-- Foo.svelte -->
<slot name="content">
  foo fallback
</slot> 

<!-- Bar.svelte -->
<script>import Foo from './Foo.svelte'</script>
<Foo>
    <span slot="content">
        bar fallback
    </span>
</Foo>

&lt;Bar&gt; 组件在使用 &lt;Foo/&gt; 调用时显示回退,但在使用 &lt;Bar&gt;&lt;span slot="content"&gt;bar custom&lt;/span&gt;&lt;/Bar&gt; 调用时不显示自定义内容。

你能告诉我我做错了什么吗?

<Foo/>
<!-- prints 'foo fallback': OK -->

<Foo>
    <span slot="content">foo custom</span>
</Foo>
<!-- prints 'foo custom': OK -->

<Bar/>
<!-- prints 'bar fallback': OK -->

<Bar>
    <span slot="content">bar custom</span>
</Bar>
<!-- prints 'bar fallback': KO - I would have expected 'bar custom' -->

请注意,这段代码过于简单,我的实际用例比这要复杂一些,我需要在那里使用插槽。

小提琴:https://svelte.dev/repl/5c525651eb8b4f60a6a696c1bd19f723

【问题讨论】:

你没有为Bar 定义一个槽,所以所有渲染的都是Foo 的槽。更清晰的方法是为Barrepl定义一个属性 谢谢。这是一个过于简化的代码示例,用于暴露我的问题,在我的实际用例中,一个属性不够强大,我确实需要使用插槽。 很公平,尽管您还不清楚您希望嵌套插槽如何工作。无论如何,您将插槽内容传递给 Bar 但 Bar 没有定义插槽,这是一个选项,它仍然在 Foo 内呈现传递给 Bar 的插槽内容:REPL(看起来 REPL 站点已损坏) 【参考方案1】:

您似乎想在Foo 定义的槽中渲染传递给Bar 的槽内容,但目前您还没有在Bar 中定义槽,因此无处可使用传递的内容,因此后备值总是传递给Foo

解决方案可能类似于以下内容,在Bar 中定义一个content 插槽传递给Foo 的内容插槽的范围内。

// App.svelte

<script>
    import Foo from './Foo.svelte'
    import Bar from './Bar.svelte'
</script>

Expected: <em>bar custom</em><br>
<Bar>
    <span slot="content">bar custom</span>
</Bar>
// ./Bar.svelte

<script>
  import Foo from './Foo.svelte';
</script>

<Foo>
  <span slot="content">
    <slot name="content">bar fallback</slot>
  </span>
</Foo>
// ./Foo.svelte

<slot name="content">
  foo fallback
</slot> 

REPL

【讨论】:

谢谢。这看起来不错,但这会与第三级继承中断。例如,使用从 &lt;Bar&gt; 继承的 &lt;Baz&gt; 组件并且没有后备插槽,我无法实现使用自定义内容。 svelte.dev/repl/58c4dadc8d884abd8c46e4f8edfa6ea3 虽然,这可能是另一个问题。 好吧,您刚刚复制了Foo Bar 继承中的问题,方法是未在Baz 中指定插槽。如果没有更多关于你的真实组件如何交互的背景信息,我真的无法提供更多。【参考方案2】:

我认为大多数答案都非常接近。我相信您可以通过创建一个内容和名称具有相同值的插槽来修复它。以您的示例 (Repl with full 3rd level inheritance) 为基础,

<!-- Foo.svelte -->
<slot name="content">
  foo fallback
</slot> 
<!-- Bar.svelte -->
<script>import Foo from './Foo.svelte'</script>
<Foo>
  <slot name="content" slot="content">
    bar fallback
  </slot>
</Foo>

通过这种方式,我们既可以通过插槽,也可以包含我们的新后备。

如果您希望确保 span 存在,可以根据您的用例将其放在 slot 内部或外部来完成。

<!-- Bar.svelte -->
<script>import Foo from './Foo.svelte'</script>
<!-- option 1-->
<Foo>
  <span>
    <slot name="content" slot="content">
      bar fallback
    </slot>
  </span>
</Foo>
<!-- option 2-->
<Foo>
  <slot name="content" slot="content">
    <span>
      bar fallback
    </span>
  </slot>
</Foo>

【讨论】:

以上是关于如何继承带有苗条组件的插槽?的主要内容,如果未能解决你的问题,请参考以下文章

Vue-七七创建全局组件——“Loading“ 使用extend创建组件——弹出层 单继承:vue组件间的继承。——继承js的部分 异步组件加载 异步组件工厂 组件插槽

如何正确使用 vue js Web 组件内部的插槽并应用样式

11. react 组合与继承

11. react 组合与继承

如何正确继承 Typescript 中的父组件?

qt 继承的信号不会到达插槽