Web Components

247 阅读3分钟

前言

在上篇文章 Angular视图封装模式中我们简单了解了一下 Shadow Dom。Shadow Dom只是Web Components的组成部分之一。

Web Components 是原生提供的一套功能,它允许在Web文档和Web应用程序中创建可重用的小部件或组件。

简单说就是不用框架,利用原生技术Web Components就可以封装组件,实现组件化,Web Components主要由三部分组成:

  • Custom elements(自定义元素) Custom element用于创建自定义HTML元素,提供了完整的生命周期image.png
  • HTML templates(HTML模板) HTML templates通过<template><slot>实现内容分发
  • Shadow Dom(影子DOM) Shadow Dom提供了封装的功能,使元素与主文档隔离,样式互补冲突

简单看一个例子

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <time-formatted datetime="1646472274953"></time-formatted>
  </body>
  <script>
    class TimeFormatted extends HTMLElement {
      connectedCallback() {
        let date = new Date(parseInt(this.getAttribute("datetime")));
        this.innerHTML = `${date.getFullYear()}-${date.getMonth()}-${date.getDay()}`;
      }
    }
    customElements.define("time-formatted", TimeFormatted);
  </script>
</html>

image.png

上述代码简单实现了一个 time-formatted 组件,或许你用过Angular,会觉得这和Angular太像了。

再写个例子看看

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <template id="my-article">
      <p>this is a example</p>
      <slot name="title"></slot>
      <hr>
      <slot name="content"></slot>
    </template>
    
    <my-article>
      <h3 slot="title">Web Components</h3>
      <div slot="content">Web Components 如何使用?和框架的区别是什么?是否可以替代框架呢?</div>
    </my-article>
  </body>
  <script>
    class MyArticle extends HTMLElement {
      connectedCallback() {
        const template = document.getElementById("my-article").content;
        this.attachShadow({ mode: "open" }).append(template.cloneNode(true));
      }
    }
    customElements.define("my-article", MyArticle);
  </script>
</html>

image.png 该例子中定义了一个组件my-article,并将模版template 通过shadow dom 挂在组件上,且模版中有两个具名插槽。或许你用过Vue,会觉得这和Vue太像了。没错,Vue slot的设计灵感正是来源于Web Components。 image.png 如果你想了解更多用法,请参考 教程

疑惑

在了解Web Components之后有几个问题一直很困扰我:

  1. 在原生Api支持组件化的条件下,为什么人们还是愿意去拥抱框架?
  2. 用Web Components实现的组件和用框架实现的组件有什么区别?
  3. 会不会有一天框架被淘汰了?

一段时间后

就像电影里的几年后,主人公总是变强后归来。
疑惑终于不是疑惑了。

  1. 在原生Api支持组件化的条件下,为什么人们还是愿意去拥抱框架? 组件化只是框架提供的众多便捷中的一种,每一种框架都有对应的生态,例如路由、状态管理、脚手架、测试、文档等等。。。这也就是大家愿意拥抱框架的原因吧。

  2. 用Web Components实现的组件和用框架实现的组件有什么区别? 别忘了,Web Components可是原生的,完全不依赖框架环境,如果你用Web Components实现了一个组件,你可以在Vue项目里用,也可以在Angular项目里用,完全垮框架。Vue里也提供了具体使用的方法使用自定义元素;同样在Angular中也有对应的支持。 目前已经有很多用Web Components实现的UI库了,例如腾讯推出的OMI ,微软推出的fast.design

  3. 会不会有一天框架被淘汰了? 不知从哪篇文章看到的一句话:能淘汰框架的一定是框架。我非常赞同,框架不是单一的一种技术,而是一个生态,包含很多技术。除非有一天,原生Api也形成了一个生态圈,能解决框架解决的所有问题,那可能会有部分人放弃框架选择原生,但框架也不会被淘汰,只是技术人员又多了一种选择而已。