【譯】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將隨着咱們的需求不斷增加和發展。

相關文章
相關標籤/搜索