Component 标签_web前端

年 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 在 年的 Fronteers Conference 上首次引入。两年后谷歌的 Polymer 库(基于当前提议的 polyfill)问世,但早期的实现直到 年才出现在 Chrome 和 Safari 中。

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

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

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

4.Web Component 入门?

一个 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...

一个 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 }!`;
}

Web Component 生命周期方法

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

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

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

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

Web Component 与其他元素交互

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

影子 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);
}

HTML 模板

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

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

模板在