当前位置:   article > 正文

【Web技术】1555- Web Component 探索之旅

web components mdn

Web Component 是什么?

简介

Web Components 是一套不同的技术,允许您创建可重用的定制元素(它们的功能封装在您的代码之外)并且在您的 web 应用中使用它们。

-- Web Components | MDN[1]

关于它的其它介绍:

  • 组件是前端的发展方向,现在流行的 React 和 Vue 都是组件框架。而 Web Component 相比第三方框架,原生组件简单直接,符合直觉,不用加载任何外部模块,代码量小。目前,已经发展的比较成熟,并用于生产环境。

  • 组件化开发使得我们可以将页面切割成模块便于封装和开发,而 Web Component 在此基础上,可以将每个组件渲染在独立的 DOM 树中,天然支持模块间样式和逻辑的隔离。

特性

这里会对 Web Component 的相关属性做一个简单介绍。

Web Component 特性完整代码:

https://codesandbox.io/s/snowy-darkness-jmdip7

Custom Elements

一组 Javascript API,允许您定义 Custom Elements 及其行为,然后在您的用户界面中按照需要使用它们。

window.customElements
  1. // custom button
  2. class CustomButton extends HTMLElement {
  3.   constructor() {
  4.     super();
  5.     const button = document.createElement("button");
  6.     button.innerText = this.getAttribute("name") || "custom button";
  7.     button.disabled = true;
  8.     this.appendChild(button);
  9.   }
  10. }
  11. window.customElements.define("custom-button", CustomButton);
  • window.customElements.get

该方法用来获取自定义组件的构造函数,接收一个参数,即声明的自定义组件的 name,返回构造函数。

  1. const getCustomConstructorBefore = customElements.get('custom-button');
  2. // getCustomConstructorBefore before:  undefined
  3. console.log('getCustomConstructorBefore before: ', getCustomConstructorBefore);
  4. customElements.define("custom-button", CustomButton);
  5. const getCustomConstructorAfter = customElements.get('custom-button');
  6. // getCustomConstructorAfter after:  ƒ CustomButton() {}
  7. console.log('getCustomConstructorAfter after: ', getCustomConstructorAfter);
  • window.customElements.upgrade

customElements upgrade() 方法升级节点子树中文档的所有包含 shadow dom 的(亲测,可以不包含 shadow dom)自定义元素,甚至在它们连接到主文档之前。接收一个参数,即一个自定义组件节点,无返回值。

  1. // 先创建自定义标签
  2. const el = document.createElement("spider-man");
  3. class SpiderMan extends HTMLElement {}
  4. // 后声明构造函数
  5. customElements.define("spider-man", SpiderMan);
  6. // false
  7. console.log(el instanceof SpiderMan);
  8. // 建立自定义标签与构造函数之间的绑定关系
  9. customElements.upgrade(el);
  10. // true
  11. console.log(el instanceof SpiderMan);
  • window.customElements.whenDefined

该方法用来检测并提供自定义组件被定义声明完毕的时机,接收一个参数,即自定义元素的 name,返回值是一个 Promise,若提供的 name 无效,则触发 Promise 的 catch,可以用来判断是否定义了同名的 Custom Element。

Custom Element 重复定义的报错:

5c9198e356168274535f4f6caf1643ce.png

我们可以用这个方法来捕获重复定义的报错,最推荐 define 之前先 get 一下~

  1. customElements.whenDefined('custom-button').then(() => {
  2.   customElements.define('custom-button', CustomButton);
  3. }).catch((err) => {
  4.   console.log(err, 'err-----')
  5. });

捕获的报错信息:

47d27bb68803e90446329fe1bb2ad3ad.png
生命周期

Custom Elements提供了一些生命周期函数,使得我们能在自定义元素在 DOM 中的行为变化后执行相关逻辑。

  • ConnectedCallback:当自定义元素第一次被连接到文档 DOM 时调用(类似组件 Mounted);

  • attributeChangedCallback:当自定义元素的一个属性被增加、移除或更改时被调用,需要配合静态方法 observedAttributes 来使用,设置只有注册在 observedAttributes 中的属性才被监听;

  • disconnectedCallback:当自定元素与文档 DOM 断开连接时调用(类似 Unmount);

  • adoptedCallback:当自定义元素被移动到新文档时被调用;

示例代码:

  1. class CustomButton extends HTMLElement {
  2.   constructor() {
  3.     super();
  4.     const button = document.createElement("button");
  5.     button.innerText = "custom button";
  6.     button.addEventListener("click", this.changeAttribute.bind(this));
  7.     const textSpan = document.createElement("span");
  8.     textSpan.innerText = this.getAttribute("text") || "default";
  9.     textSpan.className = "info";
  10.     this.appendChild(button);
  11.     this.appendChild(textSpan);
  12.   }
  13.   connectedCallback() {
  14.     console.log("自定义button被连接到DOM啦~");
  15.   }
  16.   // observedAttributes,定义特定属性变化时,触发attributeChangedCallback函数
  17.   // 未定义的属性改变,则不会触发回调
  18.   static get observedAttributes() {
  19.     return ["style""text"];
  20.   }
  21.   // 与observedAttributes结合使用
  22.   attributeChangedCallback(name, oldValue, newValue) {
  23.     if (
  24.       name === "text" &&
  25.       oldValue !== newValue &&
  26.       this.querySelector(".info")
  27.     ) {
  28.       this.querySelector(".info").innerText = newValue;
  29.     }
  30.   }
  31.   changeAttribute() {
  32.     this.setAttribute("text""sfsdfd");
  33.   }
  34.   disconnectedCallback() {
  35.     console.log("自定义button与DOM断开连接啦~");
  36.   }
  37.   adoptedCallback() {
  38.     // 创建一个iframe的document,并移动进去
  39.     console.log("自定义button移动到新文档啦~");
  40.   }
  41.   clickToRemove() {
  42.     // 从DOM中移除自身
  43.     this.parentNode.removeChild(this);
  44.   }
  45. }
  46. window.customElements.define("custom-button", CustomButton);
Shadow DOM

一组 Javascript API,可以将封装的“Shadow DOM”树附加到元素(与主文档分开呈现),并控制其关联的功能。通过这种方式,您可以拥有一个天然的沙箱环境,保持元素的功能私有,实现样式和脚本的隔离,不用担心与文档的其他部分发生冲突。

示例代码:

  1. class CustomShadowDOM extends HTMLElement {
  2.   constructor() {
  3.     super();
  4.     // 创建一个shadowDOM
  5.     const shadow = this.attachShadow({ mode: "open" });
  6.     const info = document.createElement("span");
  7.     const style = document.createElement("style");
  8.     const css = "span { color: red; }";
  9.     style.type = "text/css";
  10.     style.appendChild(document.createTextNode(css));
  11.     info.setAttribute("class""info");
  12.     info.textContent = this.getAttribute("text") || "default";
  13.     // shadow可以创建一个不受外部影响,切拥有内部js运行逻辑,拥有独立的
  14.     // css的自定义元素(也就是web component),
  15.     shadow.appendChild(style);
  16.     shadow.appendChild(info);
  17.   }
  18. }
  19. window.customElements.define("custom-shadow-dom", CustomShadowDOM);
  • 并非只能在 CustomElement 下使用,即便是普通的 HTMLElement 也能使用这一技术来实现样式保护,详见

    声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/93189
推荐阅读
相关标签