Web Components

核心思想:Widgets, 组件化,可复用性。

可用的框架可以参考:Polymer.md

技术构成

Custom Elements

实现了创建开发者自定义的具有 HTMLElement 属性、方法的标签。

  1. <flag-icon country="nl"></flag-icon>

本质上配合 JS 定义等价的 Class:

class FlagIcon extends HTMLElement {
  constructor() {
    super();
    this._countryCode = null;
  }
  static get observedAttributes() { return ["country"]; }
  attributeChangedCallback(name, oldValue, newValue) {
    // name will always be "country" due to observedAttributes
    this._countryCode = newValue;
    this._updateRendering();
  }
  connectedCallback() {
    this._updateRendering();
  }
  get country() {
    return this._countryCode;
  }
  set country(v) {
    this.setAttribute("country", v);
  }
  _updateRendering() {
  }
}
customElements.define("flag-icon", FlagIcon);

Shadow DOM

为 SEO 的提供便捷之路,同时通过 ShadowDOM 隐藏表现层的实现,暴露出语义化的结构标签给 HTML 文档。同时优雅地实现了:Shadow Boundary,使使用了 Shadow DOM 的 Widget 免于外部样式的干扰,同时也不会干扰外部样式

  • Shadow Root 以及 Shadow Host 等概念

Styles inside a shadow tree are scoped to the shadow tree, and don’t affect elements outside the shadow tree. Styles outside the shadow tree also don’t match selectors inside the shadow tree. However, inheritable style properties like color still inherit down from host to shadow tree.

Templates

<templates> 标签为 Web Component 的实现奠定基础。在此标签中,浏览器并不会直接渲染里面的代码(HTML, CSS, JS)而是通过 JS 的调用来和 Template 之中的代码交互。往往在实际运行环境中页面加载完之后才被创建。

HTML Imports

对 HTML 文档和文档片段的复用机制。

Demo

Use

import Web Component and use it in DOM.

<link rel="import" href="../emoji-rain/emoji-rain.html">
<emoji-rain active></emoji-rain>

define the emoji-rain custom-element.

class EmojiRain extends HTMLElement {}
window.registerElements('emoji-rain', EmojiRain);
document.body.appendChild(document.createElement('emoji-rain'));

creating a shadow-root.

const header = document.createElement('header');
const shadowRoot = header.attachShadow({ mode: 'open' });

Full Demo

<template>
  <!-- Full of image slider awesomeness -->
</template>

<script>
  // Grab our template full of slider markup and styles
  var tmpl = document.querySelector('template');

  // Create a prototype for a new element that extends HTMLElement
  var ImgSliderProto = Object.create(HTMLElement.prototype);

  // Setup our Shadow DOM and clone the template
  ImgSliderProto.createdCallback = function() {
    var root = this.createShadowRoot();
    root.appendChild(document.importNode(tmpl.content, true));
  };

  // Register our new element
  var ImgSlider = document.registerElement('img-slider', {
    prototype: ImgSliderProto
  });
</scrip>

Polymer

可以参考一个 Polymer 组件 的构成。

思考

2018年04月14日

不得不说,Vue.js / Angular 都从 Web Components 以及 Polymer 这里取了经。特别是同样的对 Template 思想、Slots 等实现。

Tools

  • Stencil: A Web Compiler for Web Components

Ref