本文翻譯自:css-tricks.com/an-introduc…javascript
前端開發正在以驚人的速度發展。曾經的前端開發,技術棧都是很簡單的,現在卻愈來愈複雜。這一點從無數的文章、教程和Twitter上就能夠看出來。在本文中,我將討論爲何Web Component是一個很好的工具,能夠在不使用複雜框架或構建步驟的狀況下提供高質量的用戶體驗,並且不存在過期的風險。在這個由五部分組成的系列的後續文章中,咱們將深刻研究每一個規範。css
本系列假設您基本瞭解HTML、CSS和JavaScript。若是您在其中一個領域感到軟弱,不用擔憂,構建自定義元素實際上簡化了許多前端開發中的複雜性。html
系列文章:前端
Web Components 由三種技術組成。這三種技術會一塊兒使用。java
<template>
標籤是在標準HTML規範中定義的。上述三種技術組成了Web Components規範。git
HTML Modules 有可能會成爲第四種技術。可是四大瀏覽器都尚未實現HTML Modules。Chrome團隊已經聲明將在將來的版本中實現HTML Modulesgithub
Web Components 在目前全部的主流瀏覽中都是可使用的,除了微軟的Edge和IE11,可是也有polyfill可使用。web
將上述的三種技術稱爲Web Components在技術上來講是準確的,Web Components這個術語自己也有一些超載。所以,每種技術均可以獨立使用或與其餘技術結合使用。換句話說,它們並不相互排斥。瀏覽器
讓咱們快速看一下上述三種技術。咱們將在其餘文章中,深刻了解他們。app
就像名字所顯示的那樣,custome elements就是HTML元素,好比</div>
、</section>
、<article>
,可是咱們經過瀏覽器的API本身給元素命名。自定義元素與標準HTML元素(尖括號中的名稱)同樣,只是它們中老是有一個破折號,如<news-slider>
或<bacon-cheesburger>
。更進一步,瀏覽器廠商們都已經承諾不會再新增帶有破折號的內置元素,避免和自定義元素產生衝突。
自定義元素包含本身的語義、行爲、標記,而且能夠跨框架和瀏覽器共享。
示例能夠參考這裏:
在這個例子中,咱們定義了咱們本身的HTML元素。不能否認的是,這個元素作的事情並很少,可是這就是最基本的自定義元素構建方法。全部的自定義元素都必須以某種方式上繼承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能夠把外部文檔中的用戶內容放到shadow root目錄中的指定位置。
示例能夠參考這裏:
適當命名的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>
複製代碼
能夠點擊這裏查看示例:
隨着Web開發愈來愈複雜,像咱們這樣的開發者開始將愈來愈多的開發推遲到Web平臺自己,而Web平臺自己也在不斷成熟。Web Components規範是一組低級API,隨着開發者的發展,這些API將隨着咱們的需求不斷增加和發展。