Svelte中自定义组件的类样式未被注册。

15

我正在使用Svelte/Sapper模板并添加了Attractions UI,但是我无法将任何类/样式应用于它们的自定义组件,就像这样:

<TextField class='search-box' type='search' />
<style>
    .search-box {
        margin-bottom: 10px;
    }
</style>

我明白了

未使用的CSS选择器“.search-box”

迄今为止,让它对我起作用的唯一方法是在样式上应用:global修饰符。

2个回答

22
我认为你想在Svelte中实现的目标目前不可能。在Svelte中,class属性不被视为特殊属性,因此它不会将样式作用域泄露到子组件中,尤其是由于子组件中不必有一个根元素(与Vue.js不同)。

因此,您不能在父组件中添加样式并期望它们能够传递到子组件中。您唯一的选择是使用:global修饰符或将样式添加到全局样式表中(直接包含在HTML中,而不是Svelte组件中)。

请注意,您可以结合使用:global和作用域样式。例如,请考虑:

<div class='local'>
    <TextField class='search-box' type='search' />
</div>

<style>
    .local :global(.search-box) {
        margin-bottom: 10px;
    }
</style>

通过这种方式,样式不会泄漏到其他组件,并且仍然仅限于该组件。


鉴于 Svelte 的类作用域方式,这似乎是您在不创建真正全局样式的情况下样式化子组件的唯一方法。只需确保将 {...$$props} 添加到您的子组件中,以便应用该类 :) - stwilz
@stwilz 要么这样做,要么导出一个名为“class”的属性(我们在Attractions中这样做)。 这实际上是我个人错过Vue的inheritAttrs的少数情况:D - Abdelrahman Abounegm
2
你是指旧的 let className = ''; export { className as class}; 吗? 那也可以,但这仍然是我对 Svelte 最不喜欢的事情之一 :( - stwilz

17

这里的问题在于Svelte无法知道class属性是指CSS类还是应用该类的位置。不要忘记以下这些都是有效的Svelte组件:

<span>Hello World</span>
<span>Hello</span>
<span>World</span>
Hello World

在第一个示例中,应该将class设置在span上,但在第二个示例中,class应该放在第一个还是第二个span上?也许两个都需要?对于最后一个示例,根本没有DOM元素,因此无法将class添加到文本节点。

由于这个原因,Svelte将标记您的class为未使用并在编译过程中删除。这符合 Svelte 单文件组件 的理念,其中所有组件的样式都包含在同一文件中。虽然你的构造方法与之相悖,但有时是一种有效的方法,这就是 :global 的作用。

请注意,您可以从TextField导出class属性,并将其应用于您选择的元素,但仍然需要将class标记为全局:

<script>
    // You have to this because class is a reserved keyword in JavaScript
    let className;
    export { className as class };
</script>
<div>
  <p>
    <span class={className}>...</span>
  <p>
  <button>...</button>
</div>

你可以从TextField中导出类属性并应用于你选择的元素。这正是所提到的Attractions库所做的。我相信问题是关于如何在不使用“:global”修饰符的情况下使用此类组件和属性。 - Abdelrahman Abounegm
这是不可能的,我的答案解释了为什么不可能。 - Stephane Vanraes
我在使用$$props.class时遇到了麻烦,因为我从npm导入库时出现错误:“$前缀是保留的,不能用于变量和导入名称”,所以我猜这种方法可能会起作用,但我不确定如何使用这种方法定义默认值?因为现在我收到有关未声明道具的恼人警告。 - TeemuK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接