在现代 Web 开发中,框架风靡一时。几乎所有现代框架都有组件的概念。 组件背后的想法是将前端逻辑分解为更小的可重用块,您可以跨页面或项目共享这些块。 一般来说,这些组件不能在其他框架中重用,并且需要一个构建过程来将它们编译为可以在浏览器中运行的 JavaScript。
如果我告诉你有一种方法可以使用普通 JavaScript 和广泛可用的浏览器 API 来构建组件,并且可以跨框架共享,你会怎么想? 现在,这已成为 Web 组件的现实。在这里,我们将快速浏览一下不同类型的 Web 组件,以及我们可以使用它们的一些功能。
Web 组件是使用自定义元素注册表定义的。这是大多数现代浏览器提供的 API。要创建 Web 组件,您只需在代码中定义它,然后将其注册到自定义元素注册表中。使用正确的命名约定注册和定义后,该组件就可以在页面中使用。
customElements.define("my-component", MyComponentClass);
Web 组件可以分为两个不同的类别。它们是自主 Web 组件 和 自定义内置元素。
自治 Web 组件 是通用 HTMLElement 类的扩展。这些组件通常更加灵活,因为您实际上是在构建自己的 HTML 元素,并且能够从头开始自定义所有行为。这包括用于渲染组件的根元素。 定义后,您可以像使用任何其他 HTML 元素一样使用自治 Web 组件。
<my-button> <p><strong>Custom Built-In Elements</strong> extend specific HTML elements. For example, you may extend the HTMLButtonElement class or the HTMLAnchorElement. These are meant to augment the functionality of existing HTML elements. To use a Custom Built-In element, you use the "is" attribute on the HTML element you are augmenting to tell it that it is an instance of the Web Component.<br> </p> <pre class="brush:php;toolbar:false"><button is="my-button"> <h3> Naming Web Components </h3> <p>When defining a Web Component, there are certain conventions that must be followed. </p> <p>Generally you will name your components similar to HTML elements with your own prefix attached to keep things simple (i.e. <my-button>). The basic rules require that the element name start with a lowercase letter, and it must include a hyphen. These guidelines will get you by for most cases, but I would recommend looking at the HTML spec if you're curious about all rules.<br> <pre class="brush:php;toolbar:false"><!--Valid--> <my-button/> <your-button/> <!--Invalid--> <My-button/> <1234-button/> <Mybutton/>
Web 组件具有特定的生命周期挂钩,用于对组件经历的不同阶段做出反应。 钩子如下:
class MyComponent extends HTMLElement { static observedAttributes = ["btntype"] connectedCallback() { // Handle when the component is attached to the DOM } disconnectedCallback() { // Handle when the component is removed from the DOM } adoptedCallback() { // Handle when the component is attached to a new DOM } attributeChangedCallback(name, oldValue, newValue) { // Trigged when the "btntype" attribute is changed since it is in the list of observedAttributes. // "name" will be the name of the attribute that changed. // "oldValue" is the value before the change. // "newValue" is the new value after the change. } }
这些生命周期钩子用于执行创建/销毁组件实例时所需的任何初始化或清理工作。 attributeChangedCallback 特别有用,因为它允许对属性值更新做出反应。 Web 组件有一个特殊的静态属性,称为“observedAttributes”,它是一个属性名称(字符串)数组,将触发 attributeChangedCallback。
可访问性是当今任何 Web 开发中的一个重要考虑因素。当涉及到 Web 组件时,您可以像在常规 HTML 或框架中一样使用 ARIA 属性,但一般来说,您将继承所使用的 HTML 元素的内置角色和辅助功能。
所有相同的准则都适用于这里和其他地方。例如,确保在构建组件时使用语义 HTML,添加可能需要的任何必要的键盘处理,并确保正确管理焦点和颜色对比度等内容。
Shadow DOM 可能是 Web 组件中最令人困惑和争议的部分。 Shadow DOM 本质上是 DOM 的一个单独作用域的部分,位于 Web 组件
Shadow DOM 主要是自治 Web 组件所关心的问题,因为自定义内置元素只是添加到现有的 HTML 元素中。 对于自治 Web 组件,表示元素的自定义标签(即
这是一个示例,您将看到“my-button”元素作为宿主,其中包含 Shadow DOM。
构建 Web 组件时,可以将 Shadow DOM 设置为两种模式。这些模式是“开放”和“封闭”。开放的 Shadow DOM 可以在 Light DOM 的 Shadow Root 之外使用 JavaScript 访问,而封闭的 Shadow DOM 则不能。
customElements.define("my-component", MyComponentClass);
您在 Shadow DOM 中定义的任何样式都在 Shadow DOM 范围内,并且不会污染文档的其余部分。 “Light DOM”(文档的其余部分)中定义的任何样式都不会穿透 Shadow DOM(CSS 变量是一个例外,但我们不会在这里讨论)。 现代浏览器确实提供了使用 CSS 使用部件直接从 Light DOM 定位 Shadow DOM 的方法。 您可以通过向标记添加部件属性来将部件添加到组件的 Shadow DOM。 然后可以使用 ::part 伪选择器在 CSS 中定位这些部分。 这非常方便,但本质上它非常有限。 您不能将子选择器与 ::part 选择器链接起来。您只能定位 Shadow DOM 中具有“part”属性的特定元素。
使用 Shadow DOM 时,可访问性也是一个重要的考虑因素。如果您曾经使用过 ARIA 属性,那么您就会熟悉“aria-scribedby”和“aria-labelledby”,它们通常会被赋予一个 ID,该 ID 引用另一个包含屏幕阅读器内容标签或描述的元素。 Shadow DOM 与样式类似,将 ID 的作用域分开,因此您无法从 Light DOM 引用位于 Shadow DOM 内的 ID,反之亦然。 当尝试提供需要动态提供的详细描述时,这可能会带来挑战,但存在解决方法,我们不会在本介绍中深入探讨。
模板和槽是可以与 Shadow DOM 结合使用来增强 Web 组件的工具。模板用于在 Web 组件中创建可重用的片段,而插槽用于暴露可以传递来自 Light DOM 的内容的“洞”。
如果您需要在 Web 组件中反复渲染一段 HTML 片段,那么模板会很方便。它们也可以在 Web 组件之外使用,但用例更有限。它们是使用“模板”标签实现的。
槽用于将内容从 Light DOM 传递到 Web 组件,并使用“槽”标签实现。如果您有一个可能需要传入动态内容的通用组件,这会很方便。一个很好的例子可能是通用卡组件,您可以在其中公开一个插槽以将标记传递到卡的主体中。 插槽具有“名称”属性,您可以提供该属性来唯一标识插槽。如果您需要将多个插槽放入 Web 组件中,这会很方便。传递内容时,您只需传递一个值为 slot="your-slot-name" 的属性,内容就会传递到具有匹配名称的插槽。
插槽和 Shadow DOM 有一个值得注意的独特交互。 插槽可以具有在没有任何内容传入的情况下呈现的默认内容。传递到插槽的内容位于 Light DOM 中,并被“浅复制”到 Shadow DOM 中。 您可以在浏览器检查器中直观地看到这一点。槽内容将在 Web 组件内呈现,但在 DOM 中,技术上内容位于 Web 组件外部并提供槽的链接。
话虽如此,这意味着所有插槽内容的样式和引用就像 Light DOM 中的任何其他内容一样。 Light DOM 中的样式会影响槽内容,而 Shadow DOM 样式则不会。 有一些 API 可用于与 Web 组件中的槽内容进行交互。
现代浏览器对 Web 组件的支持相当好。主要的例外是 Safari,它不支持自定义内置元素。 如果您需要支持 Internet Explorer 11 等旧版浏览器,则必须填充一些内容。
现在我们已经简要介绍了所有基本概念,让我们看一些示例。
这是一个名为“my-button”的自治自定义元素示例:
customElements.define("my-component", MyComponentClass);
首先要注意的是代码大部分是相同的。最大的区别是我们直接扩展了 HTMLButtonElement,然后我们在定义自定义元素的时候也声明了我们扩展了按钮。
我们还花更少的时间编写渲染元素的代码。由于我们正在扩展 HTMLButtonElement,因此该组件只是一个具有额外功能的 HTML 按钮。 我们将使用 HTML“is”属性告诉 HTML 按钮它是“my-button”。
这是现场示例:
您会再次注意到我们使用“is”属性来增强现有的 HTML 按钮元素。 您还会注意到,就像使用自治自定义元素一样,我们可以附加事件侦听器并使用按钮,就像处理任何其他 HTML 元素一样,无论如何,这在这里更有意义,因为它实际上只是一个扩展的 HTML 按钮。
Web 组件是解决创建可在不同页面和项目之间重用的可共享组件问题的一种普通方法。它们的工作方式更像普通的 HTML 元素,这可能会引起一些混乱,但最终它们非常有用,有助于解决现代框架所针对的许多相同问题。
在这里,我们对 Web 组件、围绕它们的不同概念进行了非常介绍性的研究,并通过一些快速示例展示了它们的基本功能。 从这里开始,我们可以开始更深入地研究如何使构建和使用它们变得更容易,并研究如何处理它们的一些痛点。
如果您有兴趣,请随时查看 GitHub 中的示例,也可以在 Code Pen 中使用它们。
在下一篇文章中,我们将了解如何扩展使用模板和槽,以及如何使渲染变得更容易。 请继续关注!
以上是Web 组件:简介的详细内容。更多信息请关注PHP中文网其他相关文章!