前军教程网

中小站长与DIV+CSS网页布局开发技术人员的首选CSS学习平台

2023 年 Web Component 全面介绍!

大家好,很高兴又见面了,我是"高级前端分享",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!

高级前端分享

今天给大家带来的主题是Web Component,话不多说,直接进入正题。

1.前言

项目受益于使用具有单一职责的简单、独立的模块。模块化代码被封装,因此无需担心实现。只要您知道在给定一组输入时模块将输出什么,而不一定需要了解它是如何实现该目标的。

将模块化概念应用于单一编程语言很简单,但 Web 开发需要多种技术的组合。浏览器解析 HTML、 CSS 和 JavaScript 以呈现页面的内容、样式和功能。但是三者的结合可能会遇到各种问题:

  • 相关代码可以拆分为多个文件
  • 全局样式和 JavaScript 对象会以意想不到的方式相互干扰。
  • 除了上面的问题之外,语言运行时、框架、数据库和服务器上使用的其他依赖项也会遇到这些问题

2.什么是 Web Component?

Web Component 是一种创建可在任何页面上重复使用的、高度封装、单一职责代码块的方法。比如 HTML

Web Component 虽然提供了样式和功能,但可以使用各种属性和 JavaScript API 调用进行修改。可以将任意数量的

如果您需要自己的自定义功能怎么办?例如,显示页面字数的元素?没有 HTML标签。React 和 Vue.js 等框架允许开发人员创建 Web Component,其内容、样式和功能可以在单个 JavaScript 文件中定义。其解决了许多复杂的编程问题,但请记住,框架的引入可能会带来以下问题:

  • 您必须学习如何使用该框架并随着它的发展更新您的代码。
  • 为一个框架编写的组件很少与另一个框架兼容。
  • 框架的更迭
  • 标准的 Web Components 可以添加浏览器功能,这是仅靠 JavaScript 难以实现的(例如 Shadow DOM)

幸运的是,库和框架中引入的流行概念通常会进入 Web 标准,虽然花了一些时间,但 Web Component 已经到来。

3.Web Component 发展史?

标准 Web Component 的概念由 Alex Russell 在 2011 年的 Fronteers Conference 上首次引入。两年后谷歌的 Polymer 库(基于当前提议的 polyfill)问世,但早期的实现直到 2016 年才出现在 Chrome 和 Safari 中。

浏览器供应商花时间协商细节,但 Web Components 于 2018 年添加到 Firefox 中,并于 2020 年添加到 Edge(当时微软切换到 Chromium 引擎)。可以理解的是,很少有开发人员愿意或能够采用 Web Components,最终通过稳定的 API 达到了良好的浏览器支持水平。

即使您现在还不愿意放弃您最喜欢的 React、Vue 等框架,但是 Web Components 与每个框架都兼容,并且 API 将在未来几年内得到更多支持。您可以通过文末参考文献查看 Web Components 的各种组件库。

本教程完整介绍了在没有 JavaScript 框架的情况下编写 Web Component。您将了解它们是什么以及如何将它们用于您的 Web 项目。当然,前提是您需要了解一些 HTML5、CSS 和 JavaScript 知识。

4.Web Component 入门?

4.1 一个 Web Component 例子

Web Component 是自定义 HTML 元素,例如,名称必须包含破折号,以免与 HTML 规范中正式支持的元素发生冲突。

您必须定义一个 ES2015 类来控制该元素。它可以任意命名,但 让我们从 HelloWorld 开始。这个类必须扩展 HTMLElement 接口,它表示每个 HTML 元素的默认属性和方法。

注意: Firefox 允许您扩展特定的 HTML 元素,例如 HTMLParagraphElement、HTMLImageElement 或 HTMLButtonElement。这在其他浏览器中不受支持,并且不允许您创建 Shadow DOM。

该类需要一个名为 connectedCallback()的方法,该方法在元素添加到文档时调用:

class HelloWorld extends HTMLElement {
  // connect component
  connectedCallback() {
    this.textContent = 'Hello World!';
  }
}

在此示例中,元素的文本设置为“Hello World”。该类必须在 CustomElementRegistry 中注册才能将其定义为特定元素的处理程序:

customElements.define('hello-world', HelloWorld);

当您的 JavaScript 被加载时,浏览器现在将该元素与您的 HelloWorld 类相关联。完整的 JS 代码如下:

// web component class HelloWorld extends HTMLElement { // connect component
connectedCallback() { this.textContent = 'Hello World!'; } } // register
component customElements.define( 'hello-world', HelloWorld );

CSS 内容如下:

body {
  font-family: sans-serif;
}
/*这个组件可以像任何其他元素一样在 CSS 中设置样式: */
hello-world {
  font-weight: bold;
  color: red;
}

HTML 内容如下:

A new Web Component...

4.2 一个 Web Component 添加属性

这个组件功能比较弱,因为无论如何都会输出相同的文本。与任何其他元素一样,我们可以添加 HTML 属性:

这可以用于覆盖文本输。为此,您可以向 HelloWorld 类添加一个 constructor()函数,该函数在创建每个对象时运行。它必须满足以下两个条件:

  • 调用 super()方法来初始化父 HTMLElement

-进行其他初始化。在本例中,将定义一个默认值为“World”的名称属性。

class HelloWorld extends HTMLElement {
  constructor() {
    super();
    this.name = 'World';
  }
  // more code...

因为组件只关心 name 属性,一个静态的 observedAttributes()属性应该返回一个属性数组来观察:

// component attributes
static get observedAttributes() {
  return ['name'];
}

当属性在 HTML 中定义或使用 JavaScript 更改时,将调用 attributeChangedCallback()方法,它传递了属性名称、旧值和新值:

// attribute change
attributeChangedCallback(property, oldValue, newValue) {
  if (oldValue === newValue) return;
  this[ property ] = newValue;
}

在此示例中,只会更新名称属性,但您可以根据需要添加其他属性。最后,您需要调整 connectedCallback()方法中的消息:

// connect component
connectedCallback() {
  this.textContent = `Hello ${ this.name }!`;
}

4.3 Web Component 生命周期方法

在 Web Component 状态的整个生命周期中,浏览器会自动调用六个方法。此处提供了完整列表,尽管您已经在上面的示例中看到了前四个:

  • 构造函数():它在组件首次初始化时调用。它必须调用 super()并且可以设置任何默认值或执行其他预渲染过程
  • 静态观察属性():返回浏览器将观察到的属性数组。
  • attributeChangedCallback(propertyName, oldValue, newValue):每当观察到属性发生更改时调用。那些在 HTML 中定义的属性会被立即传递,但 JavaScript 可以修改它们。
document.querySelector('hello-world').setAttribute('name', 'Everyone');

发生这种情况时,该方法可能需要触发重新渲染。

  • 连接回调():当 Web Component 附加到文档对象模型时调用此函数,它应该运行任何需要的渲染。
  • 断开连接回调():当从文档对象模型中删除 Web Component 时调用它。如果您需要清理,例如删除存储的状态或中止 Ajax 请求,这可能很有用。
  • 采用回调():当 Web 组件从一个文档移动到另一个文档时调用此函数。

4.4 Web Component 与其他元素交互

Web Components 提供了一些在 JavaScript 框架中找不到的独特功能。

4.4.1 影子 DOM

虽然上面构建的 Web Component 可以正常工作,但它不能免受外部干扰,CSS 或 JavaScript 可以对其进行修改。同样,您为组件定义的样式可能会泄露并影响其他组件。

Shadow DOM 通过将一个单独的 DOM 附加到 Web 组件来解决这个封装问题:

const shadow = this.attachShadow({ mode: 'closed' });

模式可以是:

  • “open”:外部页面中的 JavaScript 可以访问 Shadow DOM(使用 Element.shadowRoot)
  • “close” :只能在 Web Component 中访问 Shadow DOM

Shadow DOM 可以像任何其他 DOM 元素一样被操作:

connectedCallback() {
  const shadow = this.attachShadow({ mode: 'closed' });
  shadow.innerHTML = `
    
    

Hello ${ this.name }!

`; }

该组件现在在元素内呈现“Hello”文本

并为其设置样式。它不能被组件外部的 JavaScript 或 CSS 修改,尽管一些样式如字体和颜色是从页面继承的,因为它们没有明确定义。

此 Web 组件范围内的样式不会影响页面上的其他段落甚至其他组件。但是请注意,CSS 选择器可以从 Web 组件内部设置:host 来影响外部元素的样式。

:host {
  transform: rotate(180deg);
}

您还可以设置元素使用特定类时要应用的样式,例如

:host(.rotate90) {
  transform: rotate(90deg);
}

4.4.2 HTML 模板

对于更复杂的 Web Component,在脚本中定义 HTML 可能变得不切实际。模板允许您在页面中定义您的 Web Component 可以使用的 HTML 块。这有几个好处:

  • 您可以调整 HTML 代码,而无需在 JavaScript 中重写字符串
  • 无需为每种类型创建单独的 JavaScript 类,即可自定义组件
  • 在 HTML 中定义 HTML 更容易 — 并且可以在组件呈现之前在服务器或客户端上对其进行修改。

模板在