【译】Web Components简介

本文翻译自: https://css-tricks.com/an-int...
本文首发于公众号:符合预期的CoyPan

前端开发正在以惊人的速度发展。曾经的前端开发,技术栈都是很简单的,现在却愈来愈复杂。这一点从无数的文章、教程和Twitter上就能够看出来。在本文中,我将讨论为何Web Component是一个很好的工具,能够在不使用复杂框架或构建步骤的状况下提供高质量的用户体验,并且不存在过期的风险。在这个由五部分组成的系列的后续文章中,咱们将深刻研究每一个规范。javascript

本系列假设您基本了解HTML、CSS和JavaScript。若是您在其中一个领域感到软弱,不用担忧,构建自定义元素实际上简化了许多前端开发中的复杂性。css

系列文章:html

An Introduction to Web Components (本文)前端

Crafting Reusable HTML Templatesjava

Creating a Custom Element from Scratchweb

Encapsulating Style and Structure with Shadow DOM浏览器

Advanced Tooling for Web Componentsapp

到底什么是Web Components

Web Components 由三种技术组成。这三种技术会一块儿使用。框架

  1. Custome Elements。自定义元素十分简单,他们都是合法的HTML元素,拥有自定义的模板,表现以及标签名(例如:<one-dialog>)。能够经过一系列的JavaScript API来建立自定义元素。自定义元素是在标准HTML规范中定义的
  2. Shadow DOM。像一个Iframe同样,能够隔离CSS和JavaScript。这是在标准DOM规范中定义的
  3. HTML templates。用户在HTML中定义的模板,只有调用的时候才会被渲染。<template>标签是在标准HTML规范中定义的

上述三种技术组成了Web Components规范。dom

HTML Modules 有可能会成为第四种技术。可是四大浏览器都尚未实现HTML Modules。Chrome团队已经声明将在将来的版本中实现HTML Modules

Web Components 在目前全部的主流浏览中都是可使用的,除了微软的Edge和IE11,可是也有polyfill可使用。

将上述的三种技术称为Web Components在技术上来讲是准确的,Web Components这个术语自己也有一些超载。所以,每种技术均可以独立使用或与其余技术结合使用。换句话说,它们并不相互排斥。

让咱们快速看一下上述三种技术。咱们将在其余文章中,深刻了解他们。

Custome elements

就像名字所显示的那样,custome elements就是HTML元素,好比<div> 、<section>、<article>,可是咱们经过浏览器的API本身给元素命名。自定义元素与标准HTML元素(尖括号中的名称)同样,只是它们中老是有一个破折号,如<news-slider>或<bacon-cheesburger>。更进一步,浏览器厂商们都已经承诺不会再新增带有破折号的内置元素,避免和自定义元素产生冲突。

自定义元素包含本身的语义、行为、标记,而且能够跨框架和浏览器共享。

示例能够参考这里:

https://codepen.io/calebdwill...

clipboard.png

在这个例子中,咱们定义了咱们本身的HTML元素<my-component>。不能否认的是,这个元素作的事情并很少,可是这就是最基本的自定义元素构建方法。全部的自定义元素都必须以某种方式上继承HTMLElement,这样才能在浏览器上注册上该元素。

自定义元素不依赖与第三方框架。浏览器厂商们正致力于规范的向后兼容性,不过都保证只要按照规范编写的组件都不会受到API大改的影响。更重要的是,这些自定义元素在当今的主流框架(Angular、React、Vue)中,只须要稍作修改,就能够作到开箱即用。

Shadow DOM

Shadow DOM是对DOM的一个封装。这使得做者可以有效地将DOM片断彼此隔离开来,包括任何能够用做CSS选择器的东西以及与之关联的样式。一般状况下,document范围内的内容都被称为light DOM,shadow root中的内容被称为shadow DOM。

当咱们使用light DOM的时候,咱们能够经过document.querySelector('selector')来选中某个DOM,或者经过element.querySelector('selector')来获取每一个元素的子元素。一样的,shadow root的子元素能够经过shadowRoot.querySelector来获取,这里的shadowRoot是一个document fragment。不一样的地方是,shadow root的子元素没法在light dom中被选中。例如,若是咱们的shadow root中有一个<button>,使用shadowRoot.querySelector('button')能够获得咱们的button,可是调用document的querySelector就取不到这个button,由于这个button属于不一样的DocumentOrShadowRoot实例。样式选择器也是同样的。

从某种意义上来讲,shadow dom有点像一个iframe,其中的内容与document的其余部分隔开了。不过,当咱们建立一个shadow root的时候,咱们仍然能够彻底控制页面中这部分的内容,只是说须要在必定的做用域下。这就是咱们所说的封装。

若是你曾经写过一个重用相同的id或者依赖CSS-in-JS工具,CSS命名策略(好比BEM)的组件,shadow dom或许提高你的开发体验。

想象一下以下的场景:

<div>
  <div id="example">
    <!-- Pseudo-code used to designate a shadow root -->
    <#shadow-root>
      <style>
      button {
        background: tomato;
        color: white;
      }
      </style>
      <button id="button">This will use the CSS background tomato</button>
    </#shadow-root>
  </div>
  <button id="button">Not tomato</button>
</div>

除了<#shadow-root>的伪代码(没有HTML元素,用来分割shadow的边界),HTML是彻底合法的。为了实现上面的HTML,咱们须要运行下面的代码:

const shadowRoot = document.getElementById('example').attachShadow({ mode: 'open' });
shadowRoot.innerHTML = `<style>
button {
  color: tomato;
}
</style>
<button id="button">This will use the CSS color tomato <slot></slot></button>`;

shadow root也可使用<slot>元素来从其内部的文档内容中包含内容。使用slot能够把外部文档中的用户内容放到shadow root目录中的指定位置。

示例能够参考这里:

https://codepen.io/calebdwill...

clipboard.png

HTML templates

适当命名的HTML<template>元素容许咱们在正常HTML流中消除代码的可重用模板。这些模板不会当即被渲染,但能够在之后使用。

<template id="book-template">
  <li><span class="title"></span> &mdash; <span class="author"></span></li>
</template>

<ul id="books"></ul>

上面的例子不会渲染任何的东西,直到咱们使用script操做了这个模板,实例化代码并告诉浏览器如何操做它。

const fragment = document.getElementById('book-template');
const books = [
  { title: 'The Great Gatsby', author: 'F. Scott Fitzgerald' },
  { title: 'A Farewell to Arms', author: 'Ernest Hemingway' },
  { title: 'Catch 22', author: 'Joseph Heller' }
];

books.forEach(book => {
  // Create an instance of the template content
  const instance = document.importNode(fragment.content, true);
  // Add relevant content to the template
  instance.querySelector('.title').innerHTML = book.title;
  instance.querySelector('.author').innerHTML = book.author;
  // Append the instance ot the DOM
  document.getElementById('books').appendChild(instance);
});
请注意,此示例建立了一个模板(<template id=“book template”>),而不使用任何其余Web Components技术,再次说明Web Components中的三种技术能够独立使用或共同使用。

表面上,可使用模板API书写一个任意结构的模板,而且在后续的代码中建立这个模板。站点上的另一个页面可能会使用相同的服务,可是使用另外的结构来建立模板:

<template id="book-template">
  <li><span class="author"></span>'s classic novel <span class="title"></span></li>
</template>

<ul id="books"></ul>

能够点击这里查看示例:

https://codepen.io/calebdwill...

总结

随着Web开发愈来愈复杂,像咱们这样的开发者开始将愈来愈多的开发推迟到Web平台自己,而Web平台自己也在不断成熟。Web Components规范是一组低级API,随着开发者的发展,这些API将随着咱们的需求不断增加和发展。

相关文章
相关标签/搜索