代码块的 Web 组件

Avatar of Chris Coyier
Chris Coyier

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

我们会讲到这一点,但首先,让我们先来个冗长的介绍。

我仍然不确定何时应该使用原生 Web 组件。其模板功能并不特别强大,所以这对我没有吸引力。它没有状态管理,而我喜欢有标准的方式来处理状态。如果我无论如何都要使用另一个组件库,那么我似乎会坚持使用它。所以,目前,我的清单是这样的

  • 不使用任何其他具有组件的 JavaScript 框架
  • 模板需求并不特别复杂
  • 不需要特别高性能的重新渲染
  • 不需要状态管理

我相信有一些工具可以帮助解决这些问题以及更多问题(devMode 的这一期节目中的一些来自 Stencil 的人谈到了这一点),但如果我要使用工具,我就会更倾向于使用框架,并且可能不会使用框架加上另一个有很多重叠功能的东西

之所以倾向于使用原生 Web 组件的原因是

  • 它们是原生的。无需下载框架。
  • Shadow DOM 是一种真正的封装方式,框架无法真正做到这一点。
  • 我可以构建自己的 HTML 元素,并在 HTML 中使用它,并设计自己的 API。

原生 Web 组件的最佳应用场景似乎是设计系统组件。您可以为系统中的组件构建自己的小型 API,人们可以使用它,这种方式比仅仅复制粘贴这段 HTML 代码要安全得多。而且我认为,如果系统使用者想要自带框架,他们也可以。

因此,您可以使用类似<our-tabs active-tab="3">而不是<div class="tabs"> ... <a href="#3" class="tab-is-active">。当更改传播到各处时,组件的重构肯定变得容易得多。

我在 CSS-Tricks 上的<circle-text>组件中使用了它们。它以半径作为参数,并通过内容传递内容,并输出一个执行此操作的<svg>。它为我们提供了一个很好的 API 来编写抽象了复杂性的内容。

所以!

我想到“代码块”可能是 Web 组件的一个不错的用例。

  • 它的 API 会很不错,因为您可以使用属性来控制有用的东西,并将代码本身作为内容(这是一个很好的后备方案)。
  • 它实际上不需要状态。
  • 语法高亮是一个很大的 CSS 块,所以将它隔离在 Shadow DOM 中会很酷。
  • 它可以具有有用的功能,例如“点击复制”按钮,人们可能会喜欢它。

总而言之,它可能让人感觉像是一个“是的,我可以使用它”的组件。

这可能还没有真正准备好投入生产(一方面,它还没有发布到 npm 等),但到目前为止,我已经做到了以下这些

这是一个想法倾倒!

  • 当一个组件依赖于第三方库时,你会怎么做?这里的语法高亮是使用 Prism.js 完成的。为了使其更加隔离,我想您可以将整个库复制粘贴到某个地方,但这似乎很愚蠢。也许你只需要记录它?
  • 尽管 Shadow DOM 很酷且有用,但Web 组件的样式设置似乎还没有一个很好的方案
  • 提取预格式化的文本并在模板中使用非常奇怪。我相信可以在不使用自定义元素内部的<pre>标签的情况下做到这一点,但如果你从<pre>中获取内容,它显然要容易得多。这使得这里的 API 略微不那么友好(因为我更喜欢单独使用<code-block>)。
  • 我想知道将另一个库需要的属性传递给它的最佳实践是什么。例如,使用data-lang="CSS"是否可以(感觉更好),然后在模板中将其转换为class="language-css",因为这是 Prism 需要的?或者最好将属性按原样传递?(我选择了后者。)
  • 人们抱怨原生 Web 组件中没有真正的“生命周期方法”,但至少你有一个:当组件渲染时:connectedCallback。所以,我想你应该在执行最终的shadowRoot.appendChild(node);之前完成所有 HTML 操作。我这里没有这样做,而是运行 Prism 遍历整个shadowRoot,在它被附加之后。只是这样看起来有效。我想可能更好,也可能做到在之前就完成,而不是允许注入跨度等导致的所有重绘。
  • 这一切的重点是一个不错的 API。在我看来,如果能够将未转义的 HTML 放入其中进行高亮显示,并且它可以为你转义它,那么事情会更好。但这会导致后备方案实际渲染该 HTML,这可能是错误的(甚至在理论上是不安全的)。对此有什么好的解决方法?也许将 HTML 放入 HTML 注释中,并测试<!--是否是内容的开头,并将其作为特殊情况处理?

无论如何,如果你想分叉它或用它做一些更花哨的事情,请告诉我。也许我们最终可以将其发布到 npm 或其他地方。我们将看看人们认为它有多有用。