为什么 Svelte 不将标记范围限定在类下,而是使用单个标记.class来设置组件样式?



当一个组件有一些CSS样式时,很自然地使用

.my-component-01 h1 { ... }
.my-component-01 h2 { ... }

限定样式的范围,但 Svelte 使用

h1.svelte-hlsza1{color:orange}
h2.svelte-hlsza1{background:yellow}

实际上将其范围限定在某个类(top 方法(下是否更健壮,因为至少在 HTML 标记中,编译的代码可以只是:

<div class="svelte-hlsza1">
<h1> ...
<h2> ...

而不是每次都重复类名。(我认为特异性是相同的:1 个类和 1 个标签名称(。

因为 Svelte 不需要单个顶级元素。

<!-- no problem for Svelte -->
<h1>...</h1>
<h2>...</h2>

事实上,它甚至根本不需要元素。

<script>...</script>
<!-- this is the end of the component (still no problem for Svelte) -->

无论什么。。。如果没有根元素,则单个包装类策略不适用。

此外,这样做不仅会局限于当前组件,还会局限于当前组件及其子组件。请考虑以下示例:

<!-- Scoped.svelte -->
<style>
span { color: red }
</style>
<div>
<span>I should be red</span>
</div>
<slot />
<!-- App.svelte -->
<script>
import Scoped from './Scoped.svelte'
</script>
<Scoped>
<span>I should not be red</span>
</Scoped>

App.svelte中的<span>不是ScopedDOM 组件的一部分,但它是 DOM 中组件的子组件。

注意:如果您想要限定当前组件及其子组件的范围,诀窍是使用:global伪选择器:

<style>
/* note that you do need a wrapping element, this time, to do that */
div :global(span) { color: blue }
</style>

div选择器样式是限定范围的,所以我们只针对这个组件的子组件(DOM 明智(,而不是上面。

您是正确的,特异性水平是相同的,但此规则:

.my-component-01 h1 { ... }

假设有一个元素包裹 h1,在 Svelte 中,情况并非如此。组件没有默认的父 HTML 元素,也不应该有。

例如,如果您检查此 REPL;尽管其中一个 h1 标记源自导入的组件,但两个 h1 标记在编译的标记中彼此相邻,如下所示:

<body>
<h1 class="svelte-1k0q8ta">This is green</h1>
<h1 class="svelte-1wsvnfu">This is red</h1>
</body>

如果是自然的方式,那么 Svelte 将不得不将编译的标记修改为如下所示:

<body>
<someelement class="my-component-01">
<h1>This is green</h1>
</someelement>
<someelement class="my-component-02">
<h1>This is red</h1>
</someelement>
</body>

当使用依赖于父子关系的 css-flex 或网格时,这将导致不可预测的结果。因此,尽管元素的重复类名对于经常检查浏览器的人来说可能很烦人(大多数用户不会(,但这是一种必要的邪恶,允许 CSS 按预期工作。

最新更新