本文翻譯自: 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規範。dom
HTML Modules 有可能會成爲第四種技術。可是四大瀏覽器都尚未實現HTML Modules。Chrome團隊已經聲明將在將來的版本中實現HTML Modules
Web Components 在目前全部的主流瀏覽中都是可使用的,除了微軟的Edge和IE11,可是也有polyfill可使用。
將上述的三種技術稱爲Web Components在技術上來講是準確的,Web Components這個術語自己也有一些超載。所以,每種技術均可以獨立使用或與其餘技術結合使用。換句話說,它們並不相互排斥。
讓咱們快速看一下上述三種技術。咱們將在其餘文章中,深刻了解他們。
就像名字所顯示的那樣,custome elements就是HTML元素,好比<div> 、<section>、<article>,可是咱們經過瀏覽器的API本身給元素命名。自定義元素與標準HTML元素(尖括號中的名稱)同樣,只是它們中老是有一個破折號,如<news-slider>或<bacon-cheesburger>。更進一步,瀏覽器廠商們都已經承諾不會再新增帶有破折號的內置元素,避免和自定義元素產生衝突。
自定義元素包含本身的語義、行爲、標記,而且能夠跨框架和瀏覽器共享。
示例能夠參考這裏:
https://codepen.io/calebdwill...
在這個例子中,咱們定義了咱們本身的HTML元素<my-component>。不能否認的是,這個元素作的事情並很少,可是這就是最基本的自定義元素構建方法。全部的自定義元素都必須以某種方式上繼承HTMLElement,這樣才能在瀏覽器上註冊上該元素。
自定義元素不依賴與第三方框架。瀏覽器廠商們正致力於規範的向後兼容性,不過都保證只要按照規範編寫的組件都不會受到API大改的影響。更重要的是,這些自定義元素在當今的主流框架(Angular、React、Vue)中,只須要稍作修改,就能夠作到開箱即用。
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...
適當命名的HTML<template>元素容許咱們在正常HTML流中消除代碼的可重用模板。這些模板不會當即被渲染,但能夠在之後使用。
<template id="book-template"> <li><span class="title"></span> — <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將隨着咱們的需求不斷增加和發展。