海外社媒SNS代运营Tiktok代运营公司
Revive Old Posts

营销型WordPress外贸多语言独立站建设+谷歌SEO优化+谷歌关键字广告投放,就找WP花园!深圳公司,技术实力雄厚,用效果说话!详情咨询info@wordpresshy.com

我们都有自己不想从事的项目。 代码变得难以管理,范围不断发展,快速修复应用在其他修复之上,并且结构在意大利面条式代码的重压下崩溃了。 编码可能是一件很麻烦的事情。

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

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

它们并不总是很容易混合,因为:

  • 相关代码可以拆分为三个或更多文件,并且
  • 全局样式和 JavaScript 对象可能会以意想不到的方式相互干扰。

这些问题是在服务器上使用的语言运行时、框架、数据库和其他依赖项遇到的问题之外的。

什么是 Web 组件?

Web 组件是一种创建可在任何页面上重用的封装的、单一职责的代码块的方法。

海外社媒SNS代运营Tiktok代运营公司

考虑 HTML <video> 标签。 给定一个 URL,查看者可以使用诸如播放、暂停、后退、前进和调整音量等控件。

提供了样式和功能,但您可以使用各种属性和 JavaScript API 调用进行修改。 任意数量 <video> 元素可以放在其他标签内,它们不会发生冲突。

如果您需要自己的自定义功能怎么办? 例如,显示页面上字数的元素? 没有 HTML <wordcount> 标记(还)。

React 和 Vue.js 等框架允许开发人员创建 Web 组件,其中的内容、样式和功能可以在单个 JavaScript 文件中定义。 这些解决了许多复杂的编程问题,但请记住:

  • 您必须学习如何使用该框架并随着它的发展更新您的代码。
  • 为一个框架编写的组件很少与另一个框架兼容。
  • 框架的流行度起起落落。 您将变得依赖于开发团队和用户的奇思妙想和优先事项。
  • 标准 Web Components 可以添加浏览器功能,这在单独的 JavaScript 中是很难实现的(例如 Shadow DOM)。

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

将模块化概念应用于单一编程语言很简单,但 Web 开发需要多种技术组合。 👩‍💻 在本指南中了解更多信息⬇️点击推文

Web 组件简史

在许多特定于供应商的错误启动之后,Alex Russell 在 2011 年的 Fronteers Conference 上首次引入了标准 Web 组件的概念。谷歌的 Polymer 库(一个基于当前提案的 polyfill)在两年后到来,但早期的实现并没有出现在 Chrome 和 Safari 中直到 2016 年。

浏览器供应商花了时间协商细节,但 Web Components 于 2018 年添加到 Firefox,2020 年添加到 Edge(当时微软切换到 Chromium 引擎)。

可以理解,很少有开发人员愿意或能够采用 Web 组件,但我们最终通过稳定的 API 达到了良好的浏览器支持水平。 并非一切都是完美的,但它们是基于框架的组件的日益可行的替代方案。

即使你还不愿意放弃你最喜欢的,Web Components 也兼容 每一个 框架,并且这些 API 将在未来几年内得到支持。

每个人都可以查看预先构建的 Web 组件的存储库:

……但是编写自己的代码更有趣!

本教程完整介绍了在没有 JavaScript 框架的情况下编写的 Web 组件。 您将了解它们是什么以及如何使它们适应您的 Web 项目。 您将需要一些 HTML5、CSS 和 JavaScript 的知识。

Web 组件入门

Web 组件是自定义的 HTML 元素,例如 <hello-world></hello-world>. 该名称必须包含一个破折号,以免与 HTML 规范中正式支持的元素发生冲突。

您必须定义一个 ES2015 类来控制元素。 它可以命名为任何名称,但 HelloWorld 是常见的做法。 它必须扩展 HTMLElement 接口,该接口代表每个 HTML 元素的默认属性和方法。

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

为了做任何有用的事情,该类需要一个名为 连接回调() 当元素添加到文档时调用:

class HelloWorld extends HTMLElement {

  // connect component
  connectedCallback() {
    this.textContent="Hello World!";
  }

}

在此示例中,元素的文本设置为“Hello World”。

必须使用 CustomElementRegistry 注册该类才能将其定义为特定元素的处理程序:

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

浏览器现在关联 <hello-world> 元素与你 你好,世界 加载 JavaScript 时的类(例如 <script type="module" src="https://kinsta.com/blog/web-components/./helloworld.js"></script>)。

您现在有一个自定义元素!

CodePen 演示

这个组件可以像任何其他元素一样在 CSS 中设置样式:

hello-world {
  font-weight: bold;
  color: red;
}

添加属性

该组件无益,因为无论如何都会输出相同的文本。 像任何其他元素一样,我们可以添加 HTML 属性:

<hello-world name="Craig"></hello-world>

这可能会覆盖文本,因此“Hello Craig!” 被陈列。 为此,您可以添加一个 构造函数() 功能到 你好,世界 类,在创建每个对象时运行。 它必须:

  1. 打电话给 极好的() 初始化父 HTMLElement 的方法,以及
  2. 进行其他初始化。 在这种情况下,我们将定义一个 姓名 设置为默认值“World”的属性:
class HelloWorld extends HTMLElement {

  constructor() {
    super();
    this.name="World";
  }

  // more code...

你的组件只关心 姓名 属性。 一个静电 观察到的属性() 属性应该返回一组要观察的属性:

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

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

// attribute change
attributeChangedCallback(property, oldValue, newValue) {

  if (oldValue === newValue) return;
  this[ property ] = newValue;

}

在这个例子中,只有 姓名 属性将永远更新,但您可以根据需要添加其他属性。

WordPress花园建议你也读一下这篇文章  有多少 WordPress 插件太多了?

最后,您需要调整消息中的 连接回调() 方法:

// connect component
connectedCallback() {

  this.textContent = `Hello ${ this.name }!`;

}

CodePen 演示

生命周期方法

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

构造函数()

它在组件第一次初始化时被调用。 它必须调用 极好的() 并且可以设置任何默认值或执行其他预渲染过程。

静态观察属性()

返回浏览器将观察到的一组属性。

attributeChangedCallback(propertyName, 旧值,新值)

每当观察到的属性更改时调用。 那些在 HTML 中定义的会被立即传递,但 JavaScript 可以修改它们:

document.querySelector('hello-world').setAttribute('name', 'Everyone');

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

连接回调()

当 Web 组件附加到文档对象模型时,将调用此函数。 它应该运行任何需要的渲染。

断开的回调()

当从文档对象模型中删除 Web 组件时调用它。 如果您需要清理,例如删除存储的状态或中止 Ajax 请求,这可能很有用。

采用回调()

当 Web 组件从一个文档移动到另一个文档时调用此函数。 您可能会发现它的用途,尽管我一直在努力想出任何情况!

Web 组件如何与其他元素交互

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

影子 DOM

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

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

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

模式可以是:

  1. “打开” — 外层页面的 JavaScript 可以访问 Shadow DOM(使用 Element.shadowRoot),或者
  2. “关闭” — Shadow DOM 只能在 Web 组件中访问。

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

connectedCallback() {

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

  shadow.innerHTML = `
    <style>
      p {
        text-align: center;
        font-weight: normal;
        padding: 1em;
        margin: 0 0 2em 0;
        background-color: #eee;
        border: 1px solid #666;
      }
    </style>

    <p>Hello ${ this.name }!</p>`;

}

该组件现在将“Hello”文本呈现在 <p> 元素和样式。 它不能被组件外的 JavaScript 或 CSS 修改,尽管字体和颜色等一些样式是从页面继承的,因为它们没有明确定义。

CodePen 演示

此 Web 组件范围内的样式不能影响页面上的其他段落甚至其他 <hello-world> 成分。

请注意,CSS :host 选择器可以设置外部样式 <hello-world> Web 组件中的元素:

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

您还可以设置元素使用特定类时应用的样式,例如 <hello-world class="rotate90">

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

HTML 模板

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

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

模板定义在 <template> 标签,并且分配一个 ID 以便您可以在组件类中引用它是实用的。 这个例子用三段来显示“Hello”消息:

<template id="hello-world">

  <style>
    p {
      text-align: center;
      font-weight: normal;
      padding: 0.5em;
      margin: 1px 0;
      background-color: #eee;
      border: 1px solid #666;
    }
  </style>

  <p class="hw-text"></p>
  <p class="hw-text"></p>
  <p class="hw-text"></p>

</template>

Web Component 类可以访问此模板、获取其内容并克隆元素以确保您在任何使用它的地方创建唯一的 DOM 片段:

const template = document.getElementById('hello-world').content.cloneNode(true);

DOM 可以直接修改并添加到 Shadow DOM 中:

connectedCallback() {

  const

    shadow = this.attachShadow({ mode: 'closed' }),
    template = document.getElementById('hello-world').content.cloneNode(true),
    hwMsg = `Hello ${ this.name }`;

  Array.from( template.querySelectorAll('.hw-text') )
    .forEach( n => n.textContent = hwMsg );

  shadow.append( template );

}

CodePen 演示

模板槽

插槽允许您自定义模板。 假设你…

营销型WordPress外贸多语言独立站建设+谷歌SEO优化+谷歌关键字广告投放,就找WP花园!深圳公司,技术实力雄厚,用效果说话!详情咨询info@wordpresshy.com

海外社媒SNS代运营Tiktok代运营公司
Revive Old Posts