【外评】“Web 组件”不是好的技术方向

Web 组件是一种在 Web 上创建可复用、自定义 HTML 元素的技术,包括 Shadow DOM、Custom Elements 和 HTML Templates。尽管 Web 组件带来了很多好处,如模块化、复用性和封装性,但它们也存在一些问题和挑战,可能导致一些开发者认为它们是“有害”的。

原文链接:https://www.mayank.co/blog/web-components-considered-harmful/

未经允许,禁止转载!

作者 | Mayank       责编 | 夏萌

译者 | 弯月

出品 | CSDN(ID:CSDNnews)

注意,本文的讨论仅限于Web组件,而不是Web组件API。事实上,我认为API本身非常有用,而且我们需要更多这样的API。

什么是Web组件?

很多教程都会告诉你,Web组件主要包括以下三点:

  1. 自定义元素
  2. 影子DOM
  3. 模板

但是,这些都是“Web组件API”。人们很容易将Web组件理解为“用于创建Web组件的API”,但实际上我们应该将其当成“用于创建组件(以及其他)的Web API”。

我不想争论具体的语义,但准确的定义更方便你理解使用Web组件API来实现非组件。

假设的例子

下面的代码是“Web组件”吗?(假设没有其他代码)

customElements.define("my-thing", class extends HTMLElement {});
const thing = document.createElement("my-thing");
document.body.appendChild(thing);

下面这些呢?

visually-hidden:not(:focus-within, :active) {
  clip-path: inset(50%) !important;
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  overflow: hidden !important;
  white-space: nowrap !important;
  user-select: none !important;
  border: 0 !important;
  margin: -1px !important;
}

下面这个呢?

<body>
<templateshadowRootMode="open">
<h1>This is the page title</h1>
<slot></slot>
</template>
<p>The page content gets slotted</p>
</body>

还有下面这个?(假设“my-checkbox.js”内含大量代码,注册了自定义元素,附加了影子树,关联了语义,添加了样式,监听了事件等等。)

<my-checkbox defaultChecked></my-checkbox>
<script src="my-checkbox.js"></script>

仔细想一想。为什么说这些是“组件”?它们不都在使用 web 组件 API 吗?

组件

React之类的JavaScript框架已经普及了“组件”的概念,所有人都能直观地理解“组件”。就连设计师都知道什么是组件,尽管他们不清楚“web 组件”究竟能做什么。

即便你没有使用过专门的组件框架,也一定接触过组件的概念。无论你称其为 HTML、模板、视图,或者其他任何东西,说到底都是一回事。

组件可以组合

我可以创建一个组件 <Input>,其中包装了一个 <input> 元素。我还可以创建一个组件<ThemedInput>,包装组件 <Input>。然后,其他人可以在 <ThemedInput>的基础上创建一个 <PasswordInput>。当所有这些组件都解析和初始化完毕后,最终的 DOM 树应该只包含一个 <input> 元素。

中间的组件并不一定和DOM树有关。浏览器不在乎网站的代码是如何组织的。换句话说,组件完全是虚构的。这并不意味着组件没有用处,只是它们存在于不同的层次。只有这样,我们才能不断组合组件,直到最顶层的 <Page> 组件。

我知道一些网站真的使用了 web 组件 API 一直组合到 <my-page>。如果这种方法对他们很有效,那么也没有人会责怪。

就个人而言,我喜欢用一个基本扁平的 DOM 树构建页面,即使这棵树由数百个中间组件组成。我使用影子DOM通常是为了隐藏一些不好的处理,大部分重要内容都位于正常的DOM中。这样,我就能更轻松地为访问者提供统一且连贯的体验。

组件是灵活的

当我需要一个 DOM 钩子来连接 JavaScript 逻辑时,就可以考虑自定义元素。同样,当我需要完全隔离时,就可以考虑影子 DOM。

但是,我也并非总是同时需要二者,或者需要其中之一。

我不想为每个组件添加一个额外的 DOM 元素(默认为 display: inline)。而且我无法使用完全隔离的组件来创建整个页面。另外,我也无法仅使用 web 组件 API 实现某些模式,比如为了在不同页面之间使用<head>而将其写成组件。

在创建组件时,使用Web 组件 API很方便,但这不是唯一的方法。如今,组件的用途已经超过了web 组件 API的功能。

准确的名称

无论是 HTML 标准还是 DOM 标准都没有提到“Web 组件”这个术语。然而,文档和学习资料中随处可见。

如果你阅读的是教你“如何创建 web 组件”的教程,你当然会认为“我创建了一个 web 组件!”或许,你确实是创建了一个 web 组件,但这种先入为主的观念会导致你的思想狭隘。

更为严重的问题是:“Web 组件”这个术语会在对组件已有既定了解的人中间引发混淆,这种混淆完全没必要,而且可以避免。当发现“web 组件”无法实现期望的组件功能时,他们就会抱怨这些 API 的局限性以及“web 组件的失败”。这会导致人们错失对这些API产生兴趣并了解这些API的机会。

所以,我的建议是:直观地表达出你的意思。我们已经有了更形象、更易于理解、更清晰的名称:

  • 自定义元素(包括未知和已定义的自定义元素)
  • 影子 DOM(包括命令式和声明式影子 DOM)
  • 插槽(包括默认和命名插槽)
  • 自定义事件
  • <template> 元素

有时,你可能会使用框架将这些东西组合成一个“组件”。但严格来说,这些只是“web 组件 API”,你可以单独以任何喜欢的方式使用它们。

或者,你也可以坚持“web 组件”的叫法。我也不强求。

本文文字及图片出自 CSDN

你也许感兴趣的:

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注