我们会讲到这一点,但首先,让我们先来个冗长的介绍。
我仍然不确定何时应该使用原生 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 或其他地方。我们将看看人们认为它有多有用。
大多数高亮显示器的问题在于它们没有使用 ES 模块,这使得它们难以使用。我和 Justin Fagnani 之前讨论过这个问题(例如,注册表和自定义命名空间)。
我的代码块 Web 组件使用 Prism 和 LitElement 以一种特别动态的加载方式来减轻重量并使其灵活:https://github.com/justinribeiro/code-block,并且可在 NPM 上使用 https://npmjs.net.cn/package/@justinribeiro/code-block 我在我的网站和内部项目中广泛使用它。它绝非完美(例如主题有效,但我还没有重新审视使其更容易处理)。
Fagnani 分叉了 Rainbow 来处理他的情况,并对其进行了更新以改善模块体验(https://npmjs.net.cn/package/@justinfagnani/rainbow)。
解决了一个小问题
事实证明,你需要去掉
所以它变成了这样
这只是你的一点小疏忽 :)
哎呀!