关于 Web 组件库的一些思考

Avatar of Chris Coyier
Chris Coyier 发布

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

最近我收到了一系列关于 Web 组件 的新闻,所以我想在这里整理一下。

在我看来,Web 组件的最佳用例之一是模式库。例如,与其像在 Bootstrap 中那样使用 <ul class="nav nav-tabs"> 或像在 Bulma 中那样使用 <div class="tabs">,你可以使用自定义元素,例如 <designsystem-tabs>

新的 Shoelace 库 使用 sl 命名空间来定义组件。它是一个完全基于 Web 组件的模式库。因此,那里的选项卡<sl-tab-group> 元素。

为什么这很好?首先,它引入了组件模型。这意味着,如果你正在处理一个组件,它拥有 一个模板和一个样式表,它们位于同一位置。查看 Shoelace 的内部实现,你可以看到这一切都是基于 Stencil 的。

另一个好处是,它意味着组件可以使用(并且确实使用了)Shadow DOM。这提供了一种来自 Web 平台本身的隔离形式。对于我们这些 CSS 开发者来说,这意味着选项卡组件中选项卡的样式是使用 .tab 类(嘿,哇,太酷了)完成的,但它在该组件中是隔离的。即使使用如此通用的名称,我也不会意外地干扰页面上使用该通用类的其他组件,也不会有一些外部 CSS 干扰这里的内部样式。Shadow DOM 就像一道安全墙,防止样式泄漏或渗入。

我刚刚看到了 FAST 框架¹,它也是一组组件。它定义的选项卡为 <fast-tabs>。这让我想起了关于 Web 组件作为模式库方法的另一个优点:它感觉像是由 API 驱动的,甚至从组件本身的名称开始,这正是你在 HTML 中使用的内容。该元素上的属性可以完全自定义。似乎新兴的标准是,你甚至不需要为控制组件的自定义属性添加 data-* 前缀。因此,如果我要创建一个选项卡组件,它可能是 <chris-tabs active-tab="lunch" variation="rounded">

也许使用 Web 组件作为模式库的最大参与者是 Ionic。 他们的选项卡<ion-tabs>,你可以使用它们而无需涉及任何其他框架(尽管除了他们自己的 Stencil 之外,它们还支持 Angular、React 和 Vue)。Ionic 在 Web 组件方面取得了长足的进步,最近 支持 Shadow Parts。以下是 Brandy Carney 对封装的再次解释

Shadow DOM 有助于防止样式从组件中泄漏并意外应用于其他元素。例如,我们将 .button 类分配给我们的 ion-button 组件。如果 Ionic Framework 用户在其自己的元素之一上设置 .button 类,它将在框架的早期版本中继承 Ionic 按钮样式。由于 ion-button 现在是一个 Shadow Web 组件,因此这不再是一个问题。

但是,由于这种封装,样式也无法渗透到 Shadow 组件的内部元素。这意味着,如果 Shadow 组件在其 Shadow 树内部渲染元素,用户将无法使用他们的 CSS 来定位内部元素。

封装是一件好事,但它确实使得样式变得“更难”(有意为之)。有一个重要的 CSS 概念需要了解:**CSS 自定义属性可以穿透 Shadow DOM**。但是,人们决定——我认为是正确的——在设计系统中将所有东西都“变量化”并不是一种明智的途径。相反,他们为 Shadow DOM 内部的每个 HTML 片段分配一个部分,例如 <div part="icon">,这使我们能够使用 CSS “从外部访问”它,例如 custom-component::part(icon) { }

我认为基于部分的样式挂钩总体上还不错,并且是此类模式库的明智发展方向,但我承认其中一部分让我感到困扰。选择器的工作方式与预期不符。例如,你无法有条件地选择事物。你也不能选择子元素或使用级联。换句话说,它只是一个一次性的操作,或者就像你用手直接穿过一层膜。你可以伸出手去抓取某个东西,或者不抓,但你完全无法做其他任何事情。

说到让人生气的事情,Andrea Giammarchi 有一个很好的观点关于 Web 组件的现状

每个开始的库,包括我的库,都建议我们应该导入库来定义原本应该是一个“可移植的自定义元素”的东西。

Google 总是建议使用 LitElement。Microsoft 想要你使用 FASTElement。Stencil 有自己的 组件。hyperHTML 有自己的 组件。**没有人只使用“原始”的 Web 组件。**这很奇怪!我认为最糟糕的部分是 Web 组件应该是一个“原生平台”的东西,这意味着我们不应该需要依赖某种特定技术才能使用它们。当我们这样做时,我们就像被绑定到它一样,就像我们仅仅使用 React 或其他任何东西一样。

Andrea 在 那篇文章中提出了一些想法,包括使用 一些新的、更小的库。我认为我想看到的是一个根本不使用任何库的模式库。

  1. FAST 在首页上连续两句话中将自己称为“界面系统”,然后又称为“UI 框架”。Shoelaces 将自己称为“库”,但我称之为“模式库”。我发现“设计系统”是描述这个概念最常用的术语,但通常比特定技术使用得更广泛。FAST 在代码本身中使用该术语来表示控制主题的包装器元素。我想说围绕所有这些东西的术语远未确定。